From 0a7482207069657f45dff6638cf43ab8870ff37b Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 25 Aug 2024 13:38:06 +0200 Subject: [PATCH 1/3] Use orjson to de-/serialize json-rpc messages --- dependencies.json | 1 + plugin/core/transports.py | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/dependencies.json b/dependencies.json index 89cc5ab0c..0b7b7aae1 100644 --- a/dependencies.json +++ b/dependencies.json @@ -3,6 +3,7 @@ ">=4096": [ "bracex", "mdpopups", + "orjson", "typing_extensions", "wcmatch" ] diff --git a/plugin/core/transports.py b/plugin/core/transports.py index b0e91f89c..76503cdd0 100644 --- a/plugin/core/transports.py +++ b/plugin/core/transports.py @@ -7,7 +7,6 @@ from queue import Queue from typing import Any, Callable, Dict, Generic, IO, Protocol, TypeVar import http -import json import os import shutil import socket @@ -17,6 +16,11 @@ import time import weakref +try: + import orjson +except ImportError: + import json + orjson = None T = TypeVar('T') T_contra = TypeVar('T_contra', contravariant=True) @@ -93,6 +97,17 @@ def _decode(message: bytes) -> dict[str, Any]: return json.loads(message.decode('utf-8')) +class OrjsonRpcProcessor(JsonRpcProcessor): + + @staticmethod + def _encode(data: dict[str, Any]) -> bytes: + return orjson.dumps(data) + + @staticmethod + def _decode(message: bytes) -> dict[str, Any]: + return orjson.loads(message) + + class ProcessTransport(Transport[T]): def __init__(self, name: str, process: subprocess.Popen | None, socket: socket.socket | None, @@ -231,7 +246,10 @@ def _stderr_loop(self) -> None: # Can be a singleton since it doesn't hold any state. -json_rpc_processor = JsonRpcProcessor() +if orjson: + json_rpc_processor = OrjsonRpcProcessor() +else: + json_rpc_processor = JsonRpcProcessor() def create_transport(config: TransportConfig, cwd: str | None, From 674ecc5cab54f9897d065c5ebd223eeebe6ab402 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Sep 2024 14:09:26 +0200 Subject: [PATCH 2/3] Simplify orjson to json fallback Decide to use orjson or json on runtime, because 1. is something pyright linter can handle 2. works without touching unit tests --- plugin/core/transports.py | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/plugin/core/transports.py b/plugin/core/transports.py index 76503cdd0..5b0d8700b 100644 --- a/plugin/core/transports.py +++ b/plugin/core/transports.py @@ -84,6 +84,8 @@ def read_data(self, reader: IO[bytes]) -> dict[str, Any] | None: @staticmethod def _encode(data: dict[str, Any]) -> bytes: + if orjson: + return orjson.dumps(data) return json.dumps( data, ensure_ascii=False, @@ -94,20 +96,11 @@ def _encode(data: dict[str, Any]) -> bytes: @staticmethod def _decode(message: bytes) -> dict[str, Any]: + if orjson: + return orjson.loads(message) return json.loads(message.decode('utf-8')) -class OrjsonRpcProcessor(JsonRpcProcessor): - - @staticmethod - def _encode(data: dict[str, Any]) -> bytes: - return orjson.dumps(data) - - @staticmethod - def _decode(message: bytes) -> dict[str, Any]: - return orjson.loads(message) - - class ProcessTransport(Transport[T]): def __init__(self, name: str, process: subprocess.Popen | None, socket: socket.socket | None, @@ -246,10 +239,7 @@ def _stderr_loop(self) -> None: # Can be a singleton since it doesn't hold any state. -if orjson: - json_rpc_processor = OrjsonRpcProcessor() -else: - json_rpc_processor = JsonRpcProcessor() +json_rpc_processor = JsonRpcProcessor() def create_transport(config: TransportConfig, cwd: str | None, From d261a95a1d0649e3065c912fa30d1d039279f84e Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Sep 2024 14:41:52 +0200 Subject: [PATCH 3/3] Satisfy pyright --- .github/workflows/main.yml | 2 +- plugin/core/transports.py | 2 +- tox.ini | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 268c9241a..a6d162b57 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,7 +41,7 @@ jobs: python-version: '3.8' - run: sudo apt update - run: sudo apt install --no-install-recommends -y x11-xserver-utils - - run: pip3 install mypy==1.7.1 flake8==5.0.4 pyright==1.1.381 --user + - run: pip3 install mypy==1.7.1 flake8==5.0.4 pyright==1.1.381 orjson==3.10.7 --user - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - run: mypy stubs - run: flake8 plugin tests diff --git a/plugin/core/transports.py b/plugin/core/transports.py index 5b0d8700b..1ea3cbbf7 100644 --- a/plugin/core/transports.py +++ b/plugin/core/transports.py @@ -7,6 +7,7 @@ from queue import Queue from typing import Any, Callable, Dict, Generic, IO, Protocol, TypeVar import http +import json import os import shutil import socket @@ -19,7 +20,6 @@ try: import orjson except ImportError: - import json orjson = None T = TypeVar('T') diff --git a/tox.ini b/tox.ini index c00122615..2297f8e58 100644 --- a/tox.ini +++ b/tox.ini @@ -23,6 +23,7 @@ deps = mypy==1.7.1 flake8==5.0.4 pyright==1.1.381 + orjson==3.10.7 commands = # mypy disabled for main code as it doesn't currently support cyclic definitions - https://github.com/python/mypy/issues/731 mypy stubs