mrpy.nvim/rplugin/python3/mrpy/yaml.py

108 lines
2.5 KiB
Python

from json import loads
from re import sub
from textwrap import dedent
from . import hints
def dump_scalar(entry: hints.JSONDataScalar) -> str:
match entry:
case None:
return "null\n"
case True:
return "true\n"
case False:
return "false\n"
case _:
return f"{entry:s}\n"
def dump(obj: dict[str, hints.JSONDataScalar | list[hints.JSONDataScalar]]) -> str:
ret = ""
for key, value in obj.items():
ret += key
ret += ":"
match value:
case list() as entries:
ret += "\n"
for entry in entries:
ret += f" - {dump_scalar(entry)}"
case entry:
ret += f" {dump_scalar(entry)}"
return ret
def load(content: str) -> hints.JSONData:
"""parse subset of yaml into ``JSONData``
>>> from pprint import pprint
>>> yaml = '''
... key1: str
... key2: "str"
... key3: 1
... key4: 2.3
... key5: 2e12
... key6: null
... key7: true
... key8: false
... key9:
... - 1
... - 23.2
... key10:
... - str
... - "str"
... '''
>>> yaml_parsed = load(yaml)
>>> compare = {
... 'key1': 'str',
... 'key2': 'str',
... 'key3': 1,
... 'key4': 2.3,
... 'key5': 2e12,
... 'key6': None,
... 'key7': True,
... 'key8': False,
... 'key9': [1, 23.2],
... 'key10': ['str', 'str'],
... }
>>> {k: yaml_parsed.get(k, None) for k in compare if compare[k] != yaml_parsed[k]}
{}
"""
ret = {}
key = None
value = None
for line in sub(r":[\s\n]*", ":\n ", dedent(content).strip()).splitlines():
if line.endswith(":"):
if key:
ret[key] = value
value = None
key = line.removesuffix(":")
elif line.startswith(" -"):
value = value or []
try:
parsed = loads(line.removeprefix(" -").strip())
except:
parsed = loads('"' + line.removeprefix(" -").strip() + '"')
value.append(parsed)
else:
try:
value = loads(line.strip())
except:
value = loads('"' + line.strip() + '"')
if key:
ret[key] = value
value = None
return ret
if __name__ == "__main__":
import doctest
doctest.testmod()