A plant nursery's label printer stores its settings as a plain text file, one key=value per line. That works until a value contains a newline (a two-line label) or a key contains =. The Basics drill fixed this with length prefixes. Here you fix it the other classic way, by escaping, so the file stays readable text.
Implement:
dumps(settings: dict[str, str]) -> strloads(text: str) -> dict[str, str]
with loads(dumps(d)) == d for every dict of strings, keeping insertion order. Use exactly this format:
- One line per entry, in the dict's order:
escape(key) + "=" + escape(value) + "\n". Every line, including the last, ends with a real newline. An empty dict gives"". escapereplaces\with\\,=with\=, and a newline with\n(backslash followed by the lettern). Nothing else changes.
dumps({"size": "small", "a=b": "line1\nline2", "dir": "C:\\labels"})
# 'size=small\na\\=b=line1\\nline2\ndir=C:\\\\labels\n'
# as the file shows it:
# size=small
# a\=b=line1\nline2
# dir=C:\\labels
loads("x=\n=y\n") # {"x": "", "": "y"}
loads("") # {}
loads must raise ValueError for a malformed file:
- non-empty text that doesn't end in a newline;
- a line with no unescaped
=, or with more than one; - a
\followed by anything other than\,=orn, or at the very end of a line; - the same key twice.
Show hint
In loads, split on real newlines, then scan each line character by character: on \ look at the next character and emit the character it stands for; an unescaped = switches from building the key to building the value.