Compare commits

..

No commits in common. "e1906539616ed5ec7515f77ead84989c045adab7" and "9a46317e6c086740359a1c13766dbb68db3cc3de" have entirely different histories.

5 changed files with 21 additions and 122 deletions

View File

@ -7,5 +7,6 @@ requires-python = ">=3.12"
dependencies = [ dependencies = [
"pydantic-settings~=2.12", "pydantic-settings~=2.12",
"pynvim~=0.6.0", "pynvim~=0.6.0",
"ruamel.yaml~=0.18.17",
"requests>=2.32.5", "requests>=2.32.5",
] ]

View File

@ -1,43 +1,8 @@
from json import loads
from typing import Any from typing import Any
from pydantic import AliasChoices, AliasPath, BaseModel, Field, field_validator
from pydantic import AliasPath, BaseModel, Field, field_validator
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
from requests import get, put
from urllib.request import Request, urlopen from ruamel.yaml import Node, Representer, ScalarNode
def get(
url: str,
query_params: dict[str, str] | None = None,
headers: dict[str, str] | None = None,
) -> str:
with urlopen(
Request(
url + ("?" + "&".join(f"{k}={v}" for k, v in query_params.items()))
if query_params
else "",
headers=headers or {},
method="GET",
),
) as resp:
return resp.read().decode("utf-8")
def put(
url: str,
data: dict[str, str] | None = None,
headers: dict[str, str] | None = None,
) -> str:
with urlopen(
Request(
url,
str(data).encode(),
headers=headers or {},
method="PUT",
),
) as resp:
return resp.read().decode("utf-8")
class ClickupTask(BaseModel): class ClickupTask(BaseModel):
@ -112,18 +77,18 @@ class ClickupSession(BaseSettings):
base_url: str = "https://api.clickup.com/api/v2" base_url: str = "https://api.clickup.com/api/v2"
def _get(self, endpoint: str, **query_params: Any) -> dict[str, Any]: def _get(self, endpoint: str, **query_params: Any) -> dict[str, Any]:
raw_data = get( with get(
self.base_url + endpoint, self.base_url + endpoint,
query_params, query_params,
headers={ headers={
"accept": "application/json", "accept": "application/json",
"Authorization": self.auth_key, "Authorization": self.auth_key,
}, },
) ) as resp:
return loads(raw_data) return resp.json()
def _put(self, endpoint: str, **body_params: Any) -> dict[str, Any]: def _put(self, endpoint: str, **body_params: Any) -> dict[str, Any]:
raw_data = put( with put(
self.base_url + endpoint, self.base_url + endpoint,
body_params, body_params,
headers={ headers={
@ -131,8 +96,8 @@ class ClickupSession(BaseSettings):
"content-type": "application/json", "content-type": "application/json",
"Authorization": self.auth_key, "Authorization": self.auth_key,
}, },
) ) as resp:
return loads(raw_data) return resp.json()
def get_tasks(self) -> list[ClickupTask]: def get_tasks(self) -> list[ClickupTask]:
data = self._get( data = self._get(

View File

@ -4,7 +4,7 @@ from pynvim import Nvim, command, plugin
from pynvim.api import Buffer from pynvim.api import Buffer
from .clickup import ClickupSession from .clickup import ClickupSession
from .hints import JSONData from .types import JSONData
from .yaml import load, dump from .yaml import load, dump

View File

@ -1,11 +1,12 @@
from json import loads from io import StringIO
from re import sub from ruamel.yaml import YAML
from textwrap import dedent
from . import hints from .types import JSONData, JSONDataScalar
yaml = YAML(typ="safe")
def dump_scalar(entry: hints.JSONDataScalar) -> str: def dump_scalar(entry: JSONDataScalar) -> str:
match entry: match entry:
case None: case None:
return "null\n" return "null\n"
@ -17,7 +18,7 @@ def dump_scalar(entry: hints.JSONDataScalar) -> str:
return f"{entry:s}\n" return f"{entry:s}\n"
def dump(obj: dict[str, hints.JSONDataScalar | list[hints.JSONDataScalar]]) -> str: def dump(obj: dict[str, JSONDataScalar | list[JSONDataScalar]]) -> str:
ret = "" ret = ""
for key, value in obj.items(): for key, value in obj.items():
ret += key ret += key
@ -34,74 +35,6 @@ def dump(obj: dict[str, hints.JSONDataScalar | list[hints.JSONDataScalar]]) -> s
return ret return ret
def load(content: str) -> hints.JSONData: def load(content: str) -> JSONData:
"""parse subset of yaml into ``JSONData`` with StringIO(content) as sio:
return yaml.load(sio) # pyright: ignore[reportAny, reportUnknownMemberType]
>>> 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()