From a4efe1fd08073ff811b2d0d29af6231d0b499d03 Mon Sep 17 00:00:00 2001 From: AcerecA Date: Fri, 2 Jan 2026 12:46:49 +0100 Subject: [PATCH] replace yaml parsed/dumper w/ simple stdlib impl --- pyproject.toml | 1 - rplugin/python3/mrpy/yaml.py | 85 ++++++++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3e6cb63..4699ba9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,5 @@ requires-python = ">=3.12" dependencies = [ "pydantic-settings~=2.12", "pynvim~=0.6.0", - "ruamel.yaml~=0.18.17", "requests>=2.32.5", ] diff --git a/rplugin/python3/mrpy/yaml.py b/rplugin/python3/mrpy/yaml.py index 6bc34dd..1d5148c 100644 --- a/rplugin/python3/mrpy/yaml.py +++ b/rplugin/python3/mrpy/yaml.py @@ -1,12 +1,11 @@ -from io import StringIO -from ruamel.yaml import YAML +from json import loads +from re import sub +from textwrap import dedent from . import hints -yaml = YAML(typ="safe") - -def dump_scalar(entry: JSONDataScalar) -> str: +def dump_scalar(entry: hints.JSONDataScalar) -> str: match entry: case None: return "null\n" @@ -18,7 +17,7 @@ def dump_scalar(entry: JSONDataScalar) -> str: return f"{entry:s}\n" -def dump(obj: dict[str, JSONDataScalar | list[JSONDataScalar]]) -> str: +def dump(obj: dict[str, hints.JSONDataScalar | list[hints.JSONDataScalar]]) -> str: ret = "" for key, value in obj.items(): ret += key @@ -35,6 +34,74 @@ def dump(obj: dict[str, JSONDataScalar | list[JSONDataScalar]]) -> str: return ret -def load(content: str) -> JSONData: - with StringIO(content) as sio: - return yaml.load(sio) # pyright: ignore[reportAny, reportUnknownMemberType] +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()