Compare commits
No commits in common. "e1906539616ed5ec7515f77ead84989c045adab7" and "9a46317e6c086740359a1c13766dbb68db3cc3de" have entirely different histories.
e190653961
...
9a46317e6c
|
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue