mercurial/thirdparty/tomli/_parser.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Sat, 26 Oct 2024 00:58:01 +0200
changeset 52100 19ae7730636a
parent 50761 2c34c9b61a4f
permissions -rw-r--r--
branching: merge stable into default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50761
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     1
import string
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     2
from types import MappingProxyType
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     3
from typing import Any, BinaryIO, Dict, FrozenSet, Iterable, NamedTuple, Optional, Tuple
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     4
import warnings
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     5
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     6
from ._re import (
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     7
    RE_DATETIME,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     8
    RE_LOCALTIME,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
     9
    RE_NUMBER,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    10
    match_to_datetime,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    11
    match_to_localtime,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    12
    match_to_number,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    13
)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    14
from ._types import Key, ParseFloat, Pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    15
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    16
ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    17
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    18
# Neither of these sets include quotation mark or backslash. They are
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    19
# currently handled as separate cases in the parser functions.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    20
ILLEGAL_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    21
ILLEGAL_MULTILINE_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t\n")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    22
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    23
ILLEGAL_LITERAL_STR_CHARS = ILLEGAL_BASIC_STR_CHARS
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    24
ILLEGAL_MULTILINE_LITERAL_STR_CHARS = ILLEGAL_MULTILINE_BASIC_STR_CHARS
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    25
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    26
ILLEGAL_COMMENT_CHARS = ILLEGAL_BASIC_STR_CHARS
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    27
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    28
TOML_WS = frozenset(" \t")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    29
TOML_WS_AND_NEWLINE = TOML_WS | frozenset("\n")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    30
BARE_KEY_CHARS = frozenset(string.ascii_letters + string.digits + "-_")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    31
KEY_INITIAL_CHARS = BARE_KEY_CHARS | frozenset("\"'")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    32
HEXDIGIT_CHARS = frozenset(string.hexdigits)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    33
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    34
BASIC_STR_ESCAPE_REPLACEMENTS = MappingProxyType(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    35
    {
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    36
        "\\b": "\u0008",  # backspace
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    37
        "\\t": "\u0009",  # tab
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    38
        "\\n": "\u000A",  # linefeed
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    39
        "\\f": "\u000C",  # form feed
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    40
        "\\r": "\u000D",  # carriage return
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    41
        '\\"': "\u0022",  # quote
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    42
        "\\\\": "\u005C",  # backslash
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    43
    }
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    44
)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    45
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    46
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    47
class TOMLDecodeError(ValueError):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    48
    """An error raised if a document is not valid TOML."""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    49
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    50
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    51
def load(fp: BinaryIO, *, parse_float: ParseFloat = float) -> Dict[str, Any]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    52
    """Parse TOML from a binary file object."""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    53
    s_bytes = fp.read()
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    54
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    55
        s = s_bytes.decode()
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    56
    except AttributeError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    57
        warnings.warn(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    58
            "Text file object support is deprecated in favor of binary file objects."
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    59
            ' Use `open("foo.toml", "rb")` to open the file in binary mode.',
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    60
            DeprecationWarning,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    61
            stacklevel=2,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    62
        )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    63
        s = s_bytes  # type: ignore[assignment]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    64
    return loads(s, parse_float=parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    65
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    66
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    67
def loads(s: str, *, parse_float: ParseFloat = float) -> Dict[str, Any]:  # noqa: C901
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    68
    """Parse TOML from a string."""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    69
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    70
    # The spec allows converting "\r\n" to "\n", even in string
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    71
    # literals. Let's do so to simplify parsing.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    72
    src = s.replace("\r\n", "\n")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    73
    pos = 0
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    74
    out = Output(NestedDict(), Flags())
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    75
    header: Key = ()
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    76
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    77
    # Parse one statement at a time
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    78
    # (typically means one line in TOML source)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    79
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    80
        # 1. Skip line leading whitespace
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    81
        pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    82
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    83
        # 2. Parse rules. Expect one of the following:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    84
        #    - end of file
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    85
        #    - end of line
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    86
        #    - comment
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    87
        #    - key/value pair
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    88
        #    - append dict to list (and move to its namespace)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    89
        #    - create dict (and move to its namespace)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    90
        # Skip trailing whitespace when applicable.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    91
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    92
            char = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    93
        except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    94
            break
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    95
        if char == "\n":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    96
            pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    97
            continue
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    98
        if char in KEY_INITIAL_CHARS:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
    99
            pos = key_value_rule(src, pos, out, header, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   100
            pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   101
        elif char == "[":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   102
            try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   103
                second_char: Optional[str] = src[pos + 1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   104
            except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   105
                second_char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   106
            if second_char == "[":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   107
                pos, header = create_list_rule(src, pos, out)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   108
            else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   109
                pos, header = create_dict_rule(src, pos, out)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   110
            pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   111
        elif char != "#":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   112
            raise suffixed_err(src, pos, "Invalid statement")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   113
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   114
        # 3. Skip comment
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   115
        pos = skip_comment(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   116
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   117
        # 4. Expect end of line or end of file
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   118
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   119
            char = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   120
        except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   121
            break
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   122
        if char != "\n":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   123
            raise suffixed_err(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   124
                src, pos, "Expected newline or end of document after a statement"
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   125
            )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   126
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   127
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   128
    return out.data.dict
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   129
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   130
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   131
class Flags:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   132
    """Flags that map to parsed keys/namespaces."""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   133
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   134
    # Marks an immutable namespace (inline array or inline table).
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   135
    FROZEN = 0
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   136
    # Marks a nest that has been explicitly created and can no longer
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   137
    # be opened using the "[table]" syntax.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   138
    EXPLICIT_NEST = 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   139
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   140
    def __init__(self) -> None:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   141
        self._flags: Dict[str, dict] = {}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   142
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   143
    def unset_all(self, key: Key) -> None:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   144
        cont = self._flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   145
        for k in key[:-1]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   146
            if k not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   147
                return
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   148
            cont = cont[k]["nested"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   149
        cont.pop(key[-1], None)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   150
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   151
    def set_for_relative_key(self, head_key: Key, rel_key: Key, flag: int) -> None:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   152
        cont = self._flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   153
        for k in head_key:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   154
            if k not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   155
                cont[k] = {"flags": set(), "recursive_flags": set(), "nested": {}}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   156
            cont = cont[k]["nested"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   157
        for k in rel_key:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   158
            if k in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   159
                cont[k]["flags"].add(flag)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   160
            else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   161
                cont[k] = {"flags": {flag}, "recursive_flags": set(), "nested": {}}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   162
            cont = cont[k]["nested"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   163
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   164
    def set(self, key: Key, flag: int, *, recursive: bool) -> None:  # noqa: A003
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   165
        cont = self._flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   166
        key_parent, key_stem = key[:-1], key[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   167
        for k in key_parent:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   168
            if k not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   169
                cont[k] = {"flags": set(), "recursive_flags": set(), "nested": {}}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   170
            cont = cont[k]["nested"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   171
        if key_stem not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   172
            cont[key_stem] = {"flags": set(), "recursive_flags": set(), "nested": {}}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   173
        cont[key_stem]["recursive_flags" if recursive else "flags"].add(flag)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   174
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   175
    def is_(self, key: Key, flag: int) -> bool:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   176
        if not key:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   177
            return False  # document root has no flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   178
        cont = self._flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   179
        for k in key[:-1]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   180
            if k not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   181
                return False
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   182
            inner_cont = cont[k]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   183
            if flag in inner_cont["recursive_flags"]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   184
                return True
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   185
            cont = inner_cont["nested"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   186
        key_stem = key[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   187
        if key_stem in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   188
            cont = cont[key_stem]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   189
            return flag in cont["flags"] or flag in cont["recursive_flags"]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   190
        return False
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   191
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   192
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   193
class NestedDict:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   194
    def __init__(self) -> None:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   195
        # The parsed content of the TOML document
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   196
        self.dict: Dict[str, Any] = {}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   197
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   198
    def get_or_create_nest(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   199
        self,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   200
        key: Key,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   201
        *,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   202
        access_lists: bool = True,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   203
    ) -> dict:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   204
        cont: Any = self.dict
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   205
        for k in key:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   206
            if k not in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   207
                cont[k] = {}
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   208
            cont = cont[k]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   209
            if access_lists and isinstance(cont, list):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   210
                cont = cont[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   211
            if not isinstance(cont, dict):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   212
                raise KeyError("There is no nest behind this key")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   213
        return cont
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   214
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   215
    def append_nest_to_list(self, key: Key) -> None:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   216
        cont = self.get_or_create_nest(key[:-1])
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   217
        last_key = key[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   218
        if last_key in cont:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   219
            list_ = cont[last_key]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   220
            try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   221
                list_.append({})
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   222
            except AttributeError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   223
                raise KeyError("An object other than list found behind this key")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   224
        else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   225
            cont[last_key] = [{}]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   226
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   227
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   228
class Output(NamedTuple):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   229
    data: NestedDict
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   230
    flags: Flags
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   231
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   232
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   233
def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   234
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   235
        while src[pos] in chars:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   236
            pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   237
    except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   238
        pass
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   239
    return pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   240
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   241
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   242
def skip_until(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   243
    src: str,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   244
    pos: Pos,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   245
    expect: str,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   246
    *,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   247
    error_on: FrozenSet[str],
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   248
    error_on_eof: bool,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   249
) -> Pos:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   250
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   251
        new_pos = src.index(expect, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   252
    except ValueError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   253
        new_pos = len(src)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   254
        if error_on_eof:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   255
            raise suffixed_err(src, new_pos, f"Expected {expect!r}") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   256
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   257
    if not error_on.isdisjoint(src[pos:new_pos]):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   258
        while src[pos] not in error_on:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   259
            pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   260
        raise suffixed_err(src, pos, f"Found invalid character {src[pos]!r}")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   261
    return new_pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   262
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   263
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   264
def skip_comment(src: str, pos: Pos) -> Pos:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   265
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   266
        char: Optional[str] = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   267
    except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   268
        char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   269
    if char == "#":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   270
        return skip_until(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   271
            src, pos + 1, "\n", error_on=ILLEGAL_COMMENT_CHARS, error_on_eof=False
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   272
        )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   273
    return pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   274
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   275
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   276
def skip_comments_and_array_ws(src: str, pos: Pos) -> Pos:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   277
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   278
        pos_before_skip = pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   279
        pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   280
        pos = skip_comment(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   281
        if pos == pos_before_skip:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   282
            return pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   283
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   284
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   285
def create_dict_rule(src: str, pos: Pos, out: Output) -> Tuple[Pos, Key]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   286
    pos += 1  # Skip "["
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   287
    pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   288
    pos, key = parse_key(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   289
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   290
    if out.flags.is_(key, Flags.EXPLICIT_NEST) or out.flags.is_(key, Flags.FROZEN):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   291
        raise suffixed_err(src, pos, f"Can not declare {key} twice")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   292
    out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   293
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   294
        out.data.get_or_create_nest(key)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   295
    except KeyError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   296
        raise suffixed_err(src, pos, "Can not overwrite a value") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   297
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   298
    if not src.startswith("]", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   299
        raise suffixed_err(src, pos, 'Expected "]" at the end of a table declaration')
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   300
    return pos + 1, key
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   301
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   302
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   303
def create_list_rule(src: str, pos: Pos, out: Output) -> Tuple[Pos, Key]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   304
    pos += 2  # Skip "[["
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   305
    pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   306
    pos, key = parse_key(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   307
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   308
    if out.flags.is_(key, Flags.FROZEN):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   309
        raise suffixed_err(src, pos, f"Can not mutate immutable namespace {key}")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   310
    # Free the namespace now that it points to another empty list item...
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   311
    out.flags.unset_all(key)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   312
    # ...but this key precisely is still prohibited from table declaration
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   313
    out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   314
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   315
        out.data.append_nest_to_list(key)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   316
    except KeyError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   317
        raise suffixed_err(src, pos, "Can not overwrite a value") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   318
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   319
    if not src.startswith("]]", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   320
        raise suffixed_err(src, pos, 'Expected "]]" at the end of an array declaration')
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   321
    return pos + 2, key
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   322
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   323
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   324
def key_value_rule(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   325
    src: str, pos: Pos, out: Output, header: Key, parse_float: ParseFloat
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   326
) -> Pos:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   327
    pos, key, value = parse_key_value_pair(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   328
    key_parent, key_stem = key[:-1], key[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   329
    abs_key_parent = header + key_parent
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   330
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   331
    if out.flags.is_(abs_key_parent, Flags.FROZEN):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   332
        raise suffixed_err(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   333
            src, pos, f"Can not mutate immutable namespace {abs_key_parent}"
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   334
        )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   335
    # Containers in the relative path can't be opened with the table syntax after this
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   336
    out.flags.set_for_relative_key(header, key, Flags.EXPLICIT_NEST)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   337
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   338
        nest = out.data.get_or_create_nest(abs_key_parent)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   339
    except KeyError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   340
        raise suffixed_err(src, pos, "Can not overwrite a value") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   341
    if key_stem in nest:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   342
        raise suffixed_err(src, pos, "Can not overwrite a value")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   343
    # Mark inline table and array namespaces recursively immutable
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   344
    if isinstance(value, (dict, list)):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   345
        out.flags.set(header + key, Flags.FROZEN, recursive=True)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   346
    nest[key_stem] = value
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   347
    return pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   348
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   349
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   350
def parse_key_value_pair(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   351
    src: str, pos: Pos, parse_float: ParseFloat
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   352
) -> Tuple[Pos, Key, Any]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   353
    pos, key = parse_key(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   354
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   355
        char: Optional[str] = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   356
    except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   357
        char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   358
    if char != "=":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   359
        raise suffixed_err(src, pos, 'Expected "=" after a key in a key/value pair')
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   360
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   361
    pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   362
    pos, value = parse_value(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   363
    return pos, key, value
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   364
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   365
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   366
def parse_key(src: str, pos: Pos) -> Tuple[Pos, Key]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   367
    pos, key_part = parse_key_part(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   368
    key: Key = (key_part,)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   369
    pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   370
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   371
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   372
            char: Optional[str] = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   373
        except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   374
            char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   375
        if char != ".":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   376
            return pos, key
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   377
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   378
        pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   379
        pos, key_part = parse_key_part(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   380
        key += (key_part,)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   381
        pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   382
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   383
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   384
def parse_key_part(src: str, pos: Pos) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   385
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   386
        char: Optional[str] = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   387
    except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   388
        char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   389
    if char in BARE_KEY_CHARS:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   390
        start_pos = pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   391
        pos = skip_chars(src, pos, BARE_KEY_CHARS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   392
        return pos, src[start_pos:pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   393
    if char == "'":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   394
        return parse_literal_str(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   395
    if char == '"':
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   396
        return parse_one_line_basic_str(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   397
    raise suffixed_err(src, pos, "Invalid initial character for a key part")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   398
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   399
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   400
def parse_one_line_basic_str(src: str, pos: Pos) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   401
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   402
    return parse_basic_str(src, pos, multiline=False)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   403
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   404
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   405
def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> Tuple[Pos, list]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   406
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   407
    array: list = []
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   408
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   409
    pos = skip_comments_and_array_ws(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   410
    if src.startswith("]", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   411
        return pos + 1, array
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   412
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   413
        pos, val = parse_value(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   414
        array.append(val)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   415
        pos = skip_comments_and_array_ws(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   416
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   417
        c = src[pos : pos + 1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   418
        if c == "]":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   419
            return pos + 1, array
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   420
        if c != ",":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   421
            raise suffixed_err(src, pos, "Unclosed array")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   422
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   423
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   424
        pos = skip_comments_and_array_ws(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   425
        if src.startswith("]", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   426
            return pos + 1, array
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   427
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   428
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   429
def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> Tuple[Pos, dict]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   430
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   431
    nested_dict = NestedDict()
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   432
    flags = Flags()
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   433
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   434
    pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   435
    if src.startswith("}", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   436
        return pos + 1, nested_dict.dict
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   437
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   438
        pos, key, value = parse_key_value_pair(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   439
        key_parent, key_stem = key[:-1], key[-1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   440
        if flags.is_(key, Flags.FROZEN):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   441
            raise suffixed_err(src, pos, f"Can not mutate immutable namespace {key}")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   442
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   443
            nest = nested_dict.get_or_create_nest(key_parent, access_lists=False)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   444
        except KeyError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   445
            raise suffixed_err(src, pos, "Can not overwrite a value") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   446
        if key_stem in nest:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   447
            raise suffixed_err(src, pos, f"Duplicate inline table key {key_stem!r}")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   448
        nest[key_stem] = value
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   449
        pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   450
        c = src[pos : pos + 1]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   451
        if c == "}":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   452
            return pos + 1, nested_dict.dict
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   453
        if c != ",":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   454
            raise suffixed_err(src, pos, "Unclosed inline table")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   455
        if isinstance(value, (dict, list)):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   456
            flags.set(key, Flags.FROZEN, recursive=True)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   457
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   458
        pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   459
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   460
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   461
def parse_basic_str_escape(  # noqa: C901
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   462
    src: str, pos: Pos, *, multiline: bool = False
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   463
) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   464
    escape_id = src[pos : pos + 2]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   465
    pos += 2
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   466
    if multiline and escape_id in {"\\ ", "\\\t", "\\\n"}:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   467
        # Skip whitespace until next non-whitespace character or end of
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   468
        # the doc. Error if non-whitespace is found before newline.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   469
        if escape_id != "\\\n":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   470
            pos = skip_chars(src, pos, TOML_WS)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   471
            try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   472
                char = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   473
            except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   474
                return pos, ""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   475
            if char != "\n":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   476
                raise suffixed_err(src, pos, 'Unescaped "\\" in a string')
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   477
            pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   478
        pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   479
        return pos, ""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   480
    if escape_id == "\\u":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   481
        return parse_hex_char(src, pos, 4)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   482
    if escape_id == "\\U":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   483
        return parse_hex_char(src, pos, 8)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   484
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   485
        return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   486
    except KeyError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   487
        if len(escape_id) != 2:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   488
            raise suffixed_err(src, pos, "Unterminated string") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   489
        raise suffixed_err(src, pos, 'Unescaped "\\" in a string') from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   490
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   491
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   492
def parse_basic_str_escape_multiline(src: str, pos: Pos) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   493
    return parse_basic_str_escape(src, pos, multiline=True)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   494
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   495
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   496
def parse_hex_char(src: str, pos: Pos, hex_len: int) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   497
    hex_str = src[pos : pos + hex_len]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   498
    if len(hex_str) != hex_len or not HEXDIGIT_CHARS.issuperset(hex_str):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   499
        raise suffixed_err(src, pos, "Invalid hex value")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   500
    pos += hex_len
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   501
    hex_int = int(hex_str, 16)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   502
    if not is_unicode_scalar_value(hex_int):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   503
        raise suffixed_err(src, pos, "Escaped character is not a Unicode scalar value")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   504
    return pos, chr(hex_int)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   505
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   506
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   507
def parse_literal_str(src: str, pos: Pos) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   508
    pos += 1  # Skip starting apostrophe
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   509
    start_pos = pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   510
    pos = skip_until(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   511
        src, pos, "'", error_on=ILLEGAL_LITERAL_STR_CHARS, error_on_eof=True
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   512
    )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   513
    return pos + 1, src[start_pos:pos]  # Skip ending apostrophe
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   514
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   515
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   516
def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   517
    pos += 3
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   518
    if src.startswith("\n", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   519
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   520
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   521
    if literal:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   522
        delim = "'"
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   523
        end_pos = skip_until(
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   524
            src,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   525
            pos,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   526
            "'''",
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   527
            error_on=ILLEGAL_MULTILINE_LITERAL_STR_CHARS,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   528
            error_on_eof=True,
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   529
        )
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   530
        result = src[pos:end_pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   531
        pos = end_pos + 3
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   532
    else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   533
        delim = '"'
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   534
        pos, result = parse_basic_str(src, pos, multiline=True)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   535
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   536
    # Add at maximum two extra apostrophes/quotes if the end sequence
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   537
    # is 4 or 5 chars long instead of just 3.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   538
    if not src.startswith(delim, pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   539
        return pos, result
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   540
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   541
    if not src.startswith(delim, pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   542
        return pos, result + delim
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   543
    pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   544
    return pos, result + (delim * 2)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   545
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   546
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   547
def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> Tuple[Pos, str]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   548
    if multiline:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   549
        error_on = ILLEGAL_MULTILINE_BASIC_STR_CHARS
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   550
        parse_escapes = parse_basic_str_escape_multiline
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   551
    else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   552
        error_on = ILLEGAL_BASIC_STR_CHARS
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   553
        parse_escapes = parse_basic_str_escape
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   554
    result = ""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   555
    start_pos = pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   556
    while True:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   557
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   558
            char = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   559
        except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   560
            raise suffixed_err(src, pos, "Unterminated string") from None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   561
        if char == '"':
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   562
            if not multiline:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   563
                return pos + 1, result + src[start_pos:pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   564
            if src.startswith('"""', pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   565
                return pos + 3, result + src[start_pos:pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   566
            pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   567
            continue
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   568
        if char == "\\":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   569
            result += src[start_pos:pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   570
            pos, parsed_escape = parse_escapes(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   571
            result += parsed_escape
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   572
            start_pos = pos
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   573
            continue
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   574
        if char in error_on:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   575
            raise suffixed_err(src, pos, f"Illegal character {char!r}")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   576
        pos += 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   577
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   578
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   579
def parse_value(  # noqa: C901
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   580
    src: str, pos: Pos, parse_float: ParseFloat
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   581
) -> Tuple[Pos, Any]:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   582
    try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   583
        char: Optional[str] = src[pos]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   584
    except IndexError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   585
        char = None
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   586
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   587
    # Basic strings
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   588
    if char == '"':
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   589
        if src.startswith('"""', pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   590
            return parse_multiline_str(src, pos, literal=False)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   591
        return parse_one_line_basic_str(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   592
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   593
    # Literal strings
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   594
    if char == "'":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   595
        if src.startswith("'''", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   596
            return parse_multiline_str(src, pos, literal=True)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   597
        return parse_literal_str(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   598
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   599
    # Booleans
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   600
    if char == "t":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   601
        if src.startswith("true", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   602
            return pos + 4, True
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   603
    if char == "f":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   604
        if src.startswith("false", pos):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   605
            return pos + 5, False
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   606
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   607
    # Dates and times
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   608
    datetime_match = RE_DATETIME.match(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   609
    if datetime_match:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   610
        try:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   611
            datetime_obj = match_to_datetime(datetime_match)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   612
        except ValueError as e:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   613
            raise suffixed_err(src, pos, "Invalid date or datetime") from e
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   614
        return datetime_match.end(), datetime_obj
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   615
    localtime_match = RE_LOCALTIME.match(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   616
    if localtime_match:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   617
        return localtime_match.end(), match_to_localtime(localtime_match)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   618
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   619
    # Integers and "normal" floats.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   620
    # The regex will greedily match any type starting with a decimal
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   621
    # char, so needs to be located after handling of dates and times.
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   622
    number_match = RE_NUMBER.match(src, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   623
    if number_match:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   624
        return number_match.end(), match_to_number(number_match, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   625
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   626
    # Arrays
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   627
    if char == "[":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   628
        return parse_array(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   629
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   630
    # Inline tables
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   631
    if char == "{":
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   632
        return parse_inline_table(src, pos, parse_float)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   633
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   634
    # Special floats
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   635
    first_three = src[pos : pos + 3]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   636
    if first_three in {"inf", "nan"}:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   637
        return pos + 3, parse_float(first_three)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   638
    first_four = src[pos : pos + 4]
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   639
    if first_four in {"-inf", "+inf", "-nan", "+nan"}:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   640
        return pos + 4, parse_float(first_four)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   641
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   642
    raise suffixed_err(src, pos, "Invalid value")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   643
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   644
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   645
def suffixed_err(src: str, pos: Pos, msg: str) -> TOMLDecodeError:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   646
    """Return a `TOMLDecodeError` where error message is suffixed with
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   647
    coordinates in source."""
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   648
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   649
    def coord_repr(src: str, pos: Pos) -> str:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   650
        if pos >= len(src):
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   651
            return "end of document"
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   652
        line = src.count("\n", 0, pos) + 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   653
        if line == 1:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   654
            column = pos + 1
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   655
        else:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   656
            column = pos - src.rindex("\n", 0, pos)
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   657
        return f"line {line}, column {column}"
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   658
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   659
    return TOMLDecodeError(f"{msg} (at {coord_repr(src, pos)})")
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   660
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   661
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   662
def is_unicode_scalar_value(codepoint: int) -> bool:
2c34c9b61a4f thirdparty: vendor tomli
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
   663
    return (0 <= codepoint <= 55295) or (57344 <= codepoint <= 1114111)