summaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/__init__.py4
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/_writer.py229
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/py.typed1
3 files changed, 234 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/__init__.py b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/__init__.py
new file mode 100644
index 0000000..6349c1f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/__init__.py
@@ -0,0 +1,4 @@
+__all__ = ("dumps", "dump")
+__version__ = "1.2.0" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT
+
+from pip._vendor.tomli_w._writer import dump, dumps
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/_writer.py b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/_writer.py
new file mode 100644
index 0000000..b1acd3f
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/_writer.py
@@ -0,0 +1,229 @@
+from __future__ import annotations
+
+from collections.abc import Mapping
+from datetime import date, datetime, time
+from types import MappingProxyType
+
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+ from collections.abc import Generator
+ from decimal import Decimal
+ from typing import IO, Any, Final
+
+ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
+ILLEGAL_BASIC_STR_CHARS = frozenset('"\\') | ASCII_CTRL - frozenset("\t")
+BARE_KEY_CHARS = frozenset(
+ "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "-_"
+)
+ARRAY_TYPES = (list, tuple)
+MAX_LINE_LENGTH = 100
+
+COMPACT_ESCAPES = MappingProxyType(
+ {
+ "\u0008": "\\b", # backspace
+ "\u000A": "\\n", # linefeed
+ "\u000C": "\\f", # form feed
+ "\u000D": "\\r", # carriage return
+ "\u0022": '\\"', # quote
+ "\u005C": "\\\\", # backslash
+ }
+)
+
+
+class Context:
+ def __init__(self, allow_multiline: bool, indent: int):
+ if indent < 0:
+ raise ValueError("Indent width must be non-negative")
+ self.allow_multiline: Final = allow_multiline
+ # cache rendered inline tables (mapping from object id to rendered inline table)
+ self.inline_table_cache: Final[dict[int, str]] = {}
+ self.indent_str: Final = " " * indent
+
+
+def dump(
+ obj: Mapping[str, Any],
+ fp: IO[bytes],
+ /,
+ *,
+ multiline_strings: bool = False,
+ indent: int = 4,
+) -> None:
+ ctx = Context(multiline_strings, indent)
+ for chunk in gen_table_chunks(obj, ctx, name=""):
+ fp.write(chunk.encode())
+
+
+def dumps(
+ obj: Mapping[str, Any], /, *, multiline_strings: bool = False, indent: int = 4
+) -> str:
+ ctx = Context(multiline_strings, indent)
+ return "".join(gen_table_chunks(obj, ctx, name=""))
+
+
+def gen_table_chunks(
+ table: Mapping[str, Any],
+ ctx: Context,
+ *,
+ name: str,
+ inside_aot: bool = False,
+) -> Generator[str, None, None]:
+ yielded = False
+ literals = []
+ tables: list[tuple[str, Any, bool]] = [] # => [(key, value, inside_aot)]
+ for k, v in table.items():
+ if isinstance(v, Mapping):
+ tables.append((k, v, False))
+ elif is_aot(v) and not all(is_suitable_inline_table(t, ctx) for t in v):
+ tables.extend((k, t, True) for t in v)
+ else:
+ literals.append((k, v))
+
+ if inside_aot or name and (literals or not tables):
+ yielded = True
+ yield f"[[{name}]]\n" if inside_aot else f"[{name}]\n"
+
+ if literals:
+ yielded = True
+ for k, v in literals:
+ yield f"{format_key_part(k)} = {format_literal(v, ctx)}\n"
+
+ for k, v, in_aot in tables:
+ if yielded:
+ yield "\n"
+ else:
+ yielded = True
+ key_part = format_key_part(k)
+ display_name = f"{name}.{key_part}" if name else key_part
+ yield from gen_table_chunks(v, ctx, name=display_name, inside_aot=in_aot)
+
+
+def format_literal(obj: object, ctx: Context, *, nest_level: int = 0) -> str:
+ if isinstance(obj, bool):
+ return "true" if obj else "false"
+ if isinstance(obj, (int, float, date, datetime)):
+ return str(obj)
+ if isinstance(obj, time):
+ if obj.tzinfo:
+ raise ValueError("TOML does not support offset times")
+ return str(obj)
+ if isinstance(obj, str):
+ return format_string(obj, allow_multiline=ctx.allow_multiline)
+ if isinstance(obj, ARRAY_TYPES):
+ return format_inline_array(obj, ctx, nest_level)
+ if isinstance(obj, Mapping):
+ return format_inline_table(obj, ctx)
+
+ # Lazy import to improve module import time
+ from decimal import Decimal
+
+ if isinstance(obj, Decimal):
+ return format_decimal(obj)
+ raise TypeError(
+ f"Object of type '{type(obj).__qualname__}' is not TOML serializable"
+ )
+
+
+def format_decimal(obj: Decimal) -> str:
+ if obj.is_nan():
+ return "nan"
+ if obj.is_infinite():
+ return "-inf" if obj.is_signed() else "inf"
+ dec_str = str(obj).lower()
+ return dec_str if "." in dec_str or "e" in dec_str else dec_str + ".0"
+
+
+def format_inline_table(obj: Mapping, ctx: Context) -> str:
+ # check cache first
+ obj_id = id(obj)
+ if obj_id in ctx.inline_table_cache:
+ return ctx.inline_table_cache[obj_id]
+
+ if not obj:
+ rendered = "{}"
+ else:
+ rendered = (
+ "{ "
+ + ", ".join(
+ f"{format_key_part(k)} = {format_literal(v, ctx)}"
+ for k, v in obj.items()
+ )
+ + " }"
+ )
+ ctx.inline_table_cache[obj_id] = rendered
+ return rendered
+
+
+def format_inline_array(obj: tuple | list, ctx: Context, nest_level: int) -> str:
+ if not obj:
+ return "[]"
+ item_indent = ctx.indent_str * (1 + nest_level)
+ closing_bracket_indent = ctx.indent_str * nest_level
+ return (
+ "[\n"
+ + ",\n".join(
+ item_indent + format_literal(item, ctx, nest_level=nest_level + 1)
+ for item in obj
+ )
+ + f",\n{closing_bracket_indent}]"
+ )
+
+
+def format_key_part(part: str) -> str:
+ try:
+ only_bare_key_chars = BARE_KEY_CHARS.issuperset(part)
+ except TypeError:
+ raise TypeError(
+ f"Invalid mapping key '{part}' of type '{type(part).__qualname__}'."
+ " A string is required."
+ ) from None
+
+ if part and only_bare_key_chars:
+ return part
+ return format_string(part, allow_multiline=False)
+
+
+def format_string(s: str, *, allow_multiline: bool) -> str:
+ do_multiline = allow_multiline and "\n" in s
+ if do_multiline:
+ result = '"""\n'
+ s = s.replace("\r\n", "\n")
+ else:
+ result = '"'
+
+ pos = seq_start = 0
+ while True:
+ try:
+ char = s[pos]
+ except IndexError:
+ result += s[seq_start:pos]
+ if do_multiline:
+ return result + '"""'
+ return result + '"'
+ if char in ILLEGAL_BASIC_STR_CHARS:
+ result += s[seq_start:pos]
+ if char in COMPACT_ESCAPES:
+ if do_multiline and char == "\n":
+ result += "\n"
+ else:
+ result += COMPACT_ESCAPES[char]
+ else:
+ result += "\\u" + hex(ord(char))[2:].rjust(4, "0")
+ seq_start = pos + 1
+ pos += 1
+
+
+def is_aot(obj: Any) -> bool:
+ """Decides if an object behaves as an array of tables (i.e. a nonempty list
+ of dicts)."""
+ return bool(
+ isinstance(obj, ARRAY_TYPES)
+ and obj
+ and all(isinstance(v, Mapping) for v in obj)
+ )
+
+
+def is_suitable_inline_table(obj: Mapping, ctx: Context) -> bool:
+ """Use heuristics to decide if the inline-style representation is a good
+ choice for a given table."""
+ rendered_inline = f"{ctx.indent_str}{format_inline_table(obj, ctx)},"
+ return len(rendered_inline) <= MAX_LINE_LENGTH and "\n" not in rendered_inline
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/py.typed b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/py.typed
new file mode 100644
index 0000000..7632ecf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/tomli_w/py.typed
@@ -0,0 +1 @@
+# Marker file for PEP 561