From aec52ecf33313554cfc6bfd7d8d824b14e5b96d2 Mon Sep 17 00:00:00 2001
From: Moosems <95927277+Moosems@users.noreply.github.com>
Date: Thu, 1 Aug 2024 13:47:39 -0600
Subject: [PATCH] V1.1.0 (#83)
* V1.1.0 version bump
* Add to do (#80)
* Combine worfklows (#82)
* Combine worfklows
* Try caching the os and packages
Trying to reduce time for workflows
* Revert "Try caching the os and packages"
This reverts commit 9a67adc95c0f485e78cea47fca28984483e002c5.
* Remove black formatting
Keep ruff formatting though
* Remove black from requirements
* Collegamento ipc (#85)
* Implement Request wrappers
* Use collegamento
* Format
* Add requirement
---
.github/PULL_REQUEST_TEMPLATE.md | 5 +-
.github/workflows/black.yml | 17 ---
.github/workflows/format.yml | 43 ++++++
.github/workflows/isort.yml | 17 ---
.github/workflows/ruff-format.yml | 17 ---
.github/workflows/ruff.yml | 17 ---
.github/workflows/tests.yml | 30 +++-
.github/workflows/windows-tests.yml | 18 ---
README.md | 2 +-
docs/source/conf.py | 2 +-
requirements-dev.txt | 2 +-
requirements.txt | 1 +
salve/__init__.py | 3 +-
salve/ipc.py | 227 +++++-----------------------
salve/misc.py | 54 -------
salve/server.py | 205 -------------------------
salve/wrappers.py | 56 +++++++
setup.py | 2 +-
18 files changed, 181 insertions(+), 537 deletions(-)
delete mode 100644 .github/workflows/black.yml
create mode 100644 .github/workflows/format.yml
delete mode 100644 .github/workflows/isort.yml
delete mode 100644 .github/workflows/ruff-format.yml
delete mode 100644 .github/workflows/ruff.yml
delete mode 100644 .github/workflows/windows-tests.yml
delete mode 100644 salve/server.py
create mode 100644 salve/wrappers.py
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 0e4988b..127a43f 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,4 +1,7 @@
Fixes #__.
-Changes in PR:
+To do:
+ - [ ] ...
+
+Cuurent changes in PR:
- ...
diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
deleted file mode 100644
index 267683f..0000000
--- a/.github/workflows/black.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Black Formatting
-
-on: push
-
-jobs:
- formatting-black:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: 3.11.1
-
- - name: Code Formatting (App)
- run: |
- pip install -r requirements-dev.txt
- black --check .
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
new file mode 100644
index 0000000..a116b10
--- /dev/null
+++ b/.github/workflows/format.yml
@@ -0,0 +1,43 @@
+name: Formatting
+
+on: push
+
+jobs:
+ formatting-isort:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.11.1
+
+ - name: Code Formatting (App)
+ run: |
+ pip install -r requirements-dev.txt
+ isort --check .
+
+ formatting-ruff:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.11.1
+
+ - name: Code Formatting (App)
+ run: |
+ pip install -r requirements-dev.txt
+ ruff format --check .
+
+ ruff-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.11.1
+
+ - name: Code Formatting (App)
+ run: |
+ pip install -r requirements-dev.txt
+ ruff check .
diff --git a/.github/workflows/isort.yml b/.github/workflows/isort.yml
deleted file mode 100644
index 3257dc9..0000000
--- a/.github/workflows/isort.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Isort Formatting
-
-on: push
-
-jobs:
- formatting-isort:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: 3.11.1
-
- - name: Code Formatting (App)
- run: |
- pip install -r requirements-dev.txt
- isort --check .
diff --git a/.github/workflows/ruff-format.yml b/.github/workflows/ruff-format.yml
deleted file mode 100644
index 16adc33..0000000
--- a/.github/workflows/ruff-format.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Ruff Formatting
-
-on: push
-
-jobs:
- formatting-ruff:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: 3.11.1
-
- - name: Code Formatting (App)
- run: |
- pip install -r requirements-dev.txt
- ruff format --check .
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
deleted file mode 100644
index 98f68b8..0000000
--- a/.github/workflows/ruff.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Ruff Check
-
-on: push
-
-jobs:
- ruff-check:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: 3.11.1
-
- - name: Code Formatting (App)
- run: |
- pip install -r requirements-dev.txt
- ruff check .
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index afc9074..427337c 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -3,7 +3,7 @@ name: Code Tests
on: push
jobs:
- testing:
+ testing-ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@@ -16,3 +16,31 @@ jobs:
pip install .
pip install -r requirements-dev.txt
python3 -m pytest .
+
+ testing-macos:
+ runs-on: macos-13
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.11.1
+
+ - name: Run tests
+ run: |
+ pip install .
+ pip install -r requirements-dev.txt
+ python3 -m pytest .
+
+ testing-windows:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: 3.11.1
+
+ - name: Run tests
+ run: |
+ pip install .
+ pip install -r requirements-dev.txt
+ python3 -m pytest . -s
diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml
deleted file mode 100644
index 25e1368..0000000
--- a/.github/workflows/windows-tests.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Code Tests (On Windows)
-
-on: push
-
-jobs:
- testing-windows:
- runs-on: windows-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: 3.11.1
-
- - name: Run tests
- run: |
- pip install .
- pip install -r requirements-dev.txt
- python3 -m pytest . -s
diff --git a/README.md b/README.md
index 2a37c7d..0aa0c13 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
Salve v1.0.0
+Salve v1.1.0
# Installation
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 9996395..617ee17 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -14,7 +14,7 @@
project = "Salve"
copyright = "2024, Moosems"
author = "Moosems"
-release = "v1.0.0"
+release = "v1.1.0"
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
diff --git a/requirements-dev.txt b/requirements-dev.txt
index bca0199..2cd615e 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,6 +3,7 @@ pygments
pyeditorconfig
beartype
token_tools
+collegamento
# Testing
pytest
@@ -10,7 +11,6 @@ pytest
# Formatting
ruff
isort
-black
# Builds
setuptools
diff --git a/requirements.txt b/requirements.txt
index fcb8d86..7bafcad 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@ pygments
pyeditorconfig
beartype
token_tools
+collegamento
diff --git a/salve/__init__.py b/salve/__init__.py
index b8c1652..3630c1e 100644
--- a/salve/__init__.py
+++ b/salve/__init__.py
@@ -2,6 +2,8 @@
beartype_this_package()
+from collegamento import Response # noqa: F401, E402
+
from .ipc import IPC # noqa: F401, E402
from .misc import ( # noqa: F401, E402
AUTOCOMPLETE,
@@ -11,6 +13,5 @@
HIGHLIGHT,
LINKS_AND_CHARS,
REPLACEMENTS,
- Response,
)
from .server_functions import is_unicode_letter # noqa: F401, E402
diff --git a/salve/ipc.py b/salve/ipc.py
index b408a6b..df81385 100644
--- a/salve/ipc.py
+++ b/salve/ipc.py
@@ -1,113 +1,51 @@
-from logging import Logger, getLogger
-from multiprocessing import Process, Queue, freeze_support
from pathlib import Path
-from random import randint
+
+from collegamento import FileClient
from .misc import (
+ AUTOCOMPLETE,
COMMAND,
COMMANDS,
+ DEFINITION,
EDITORCONFIG,
- Notification,
- Request,
- RequestQueueType,
- Response,
- ResponseQueueType,
+ HIGHLIGHT,
+ LINKS_AND_CHARS,
+ REPLACEMENTS,
+)
+from .wrappers import (
+ editorconfig_request_wrapper,
+ find_autocompletions_request_wrapper,
+ get_definition_request_wrapper,
+ get_highlights_request_wrapper,
+ get_replacements_request_wrapper,
+ get_special_tokens_request_wrapper,
)
-from .server import Server
-class IPC:
+class IPC(FileClient):
"""The IPC class is used to talk to the server and run commands. The public API includes the following methods:
- IPC.request()
- - IPC.cancel_request()
- IPC.update_file()
- IPC.remove_file()
- IPC.kill_IPC()
"""
- def __init__(self, id_max: int = 15_000) -> None:
- self.all_ids: list[int] = []
- self.id_max = id_max
- self.current_ids: dict[str, int] = {}
- self.newest_responses: dict[str, Response | None] = {}
- for command in COMMANDS:
- self.current_ids[command] = 0
- self.newest_responses[command] = None
-
- self.files: dict[str, str] = {}
-
- self.logger: Logger = getLogger("IPC")
- self.logger.info("Creating server")
- self.response_queue: ResponseQueueType = Queue()
- self.requests_queue: RequestQueueType = Queue()
- self.main_server: Process
- self.create_server()
- self.logger.info("Initialization is complete")
-
- def create_server(self) -> None:
- """Creates the main_server through a subprocess - internal API"""
- freeze_support()
- server_logger = getLogger("Server")
- self.main_server = Process(
- target=Server,
- args=(self.response_queue, self.requests_queue, server_logger),
- daemon=True,
+ def __init__(self, id_max: int = 15000) -> None:
+ super().__init__(
+ id_max=id_max,
+ commands={
+ AUTOCOMPLETE: find_autocompletions_request_wrapper,
+ REPLACEMENTS: get_replacements_request_wrapper,
+ HIGHLIGHT: get_highlights_request_wrapper,
+ EDITORCONFIG: editorconfig_request_wrapper,
+ DEFINITION: get_definition_request_wrapper,
+ LINKS_AND_CHARS: get_special_tokens_request_wrapper,
+ },
)
- self.main_server.start()
- self.logger.info("Server created")
-
- self.logger.info("Copying files to server")
- files_copy = self.files.copy()
- self.files = {}
- for file, data in files_copy.items():
- self.update_file(file, data)
- self.logger.debug("Finished copying files to server")
-
- def create_message(self, type: str, **kwargs) -> None:
- """Creates a Message based on the args and kwawrgs provided. Highly flexible. - internal API"""
- self.logger.info("Creating message for server")
- id = randint(1, self.id_max) # 0 is reserved for the empty case
- while id in self.all_ids:
- id = randint(1, self.id_max)
- self.all_ids.append(id)
-
- self.logger.debug("ID for message created")
- if not self.main_server.is_alive():
- self.logger.critical(
- "Server was killed at some point, creating server"
- )
- self.create_server()
-
- match type:
- case "request":
- self.logger.info("Creating request for server")
- command = kwargs.get("command", "")
- self.current_ids[command] = id
- request: Request = {
- "id": id,
- "type": type,
- "command": command,
- "file": "",
- }
- request.update(**kwargs)
- self.logger.debug(f"Request created: {request}")
- self.requests_queue.put(request)
- self.logger.info("Message sent")
- case "notification":
- self.logger.info("Creating notification for server")
- notification: Notification = {
- "id": id,
- "type": type,
- "remove": False,
- "file": "",
- "contents": "",
- }
- notification.update(**kwargs)
- self.logger.debug(f"Notification created: {notification}")
- self.requests_queue.put(notification)
- self.logger.info("Message sent")
- def request(
+ # Pyright likes to complain and say this won't work but it actually does
+ # TODO: Use plum or custom multiple dispatch (make it a new project for salve organization)
+ def request( # type: ignore
self,
command: COMMAND,
file: str = "",
@@ -133,96 +71,15 @@ def request(
raise Exception(f"File {file} does not exist in system!")
self.logger.debug("Sending info to create_message()")
- self.create_message(
- type="request",
- command=command,
- file=file,
- expected_keywords=expected_keywords,
- current_word=current_word,
- language=language,
- text_range=text_range,
- file_path=file_path,
- definition_starters=definition_starters,
- )
-
- def cancel_request(self, command: str) -> None:
- """Cancels a request of type command - external API"""
- if command not in COMMANDS:
- self.logger.exception(
- f"Cannot cancel command {command}, valid commands are {COMMANDS}"
- )
- raise Exception(
- f"Cannot cancel command {command}, valid commands are {COMMANDS}"
- )
-
- self.logger.info(f"Cancelled command: {command}")
- self.current_ids[command] = 0
-
- def parse_response(self, res: Response) -> None:
- """Parses main_server output line and discards useless responses - internal API"""
- self.logger.debug("Parsing server response")
- id = res["id"]
- self.all_ids.remove(id)
-
- if "command" not in res:
- self.logger.info("Response was notification response")
- return
-
- command = res["command"]
- if id != self.current_ids[command]:
- self.logger.info("Response is from old request")
- return
-
- self.logger.info(f"Response is useful for command type: {command}")
- self.current_ids[command] = 0
- self.newest_responses[command] = res
-
- def check_responses(self) -> None:
- """Checks all main_server output by calling IPC.parse_line() on each response - internal API"""
- self.logger.debug("Checking responses")
- while not self.response_queue.empty():
- self.parse_response(self.response_queue.get())
-
- def get_response(self, command: str) -> Response | None:
- """Checks responses and returns the current response of type command if it has been returned - external API"""
- self.logger.info(f"Getting response for type: {command}")
- if command not in COMMANDS:
- self.logger.exception(
- f"Cannot get response of command {command}, valid commands are {COMMANDS}"
- )
- raise Exception(
- f"Cannot get response of command {command}, valid commands are {COMMANDS}"
- )
-
- self.check_responses()
- response: Response | None = self.newest_responses[command]
- self.newest_responses[command] = None
- self.logger.info("Response retrieved")
- return response
-
- def update_file(self, file: str, current_state: str) -> None:
- """Updates files in the system - external API"""
-
- self.logger.info(f"Updating file: {file}")
- self.files[file] = current_state
-
- self.logger.debug("Notifying server of file update")
- self.create_message("notification", file=file, contents=current_state)
-
- def remove_file(self, file: str) -> None:
- """Removes a file from the main_server - external API"""
- if file not in list(self.files.keys()):
- self.logger.exception(
- f"Cannot remove file {file} as file is not in file database!"
- )
- raise Exception(
- f"Cannot remove file {file} as file is not in file database!"
- )
-
- self.logger.info("Notifying server of file deletion")
- self.create_message("notification", remove=True, file=file)
-
- def kill_IPC(self) -> None:
- """Kills the main_server when salve_ipc's services are no longer required - external API"""
- self.logger.info("Killing server")
- self.main_server.kill()
+ request: dict = {
+ "command": command,
+ "expected_keywords": expected_keywords,
+ "current_word": current_word,
+ "language": language,
+ "text_range": text_range,
+ "file_path": file_path,
+ "definition_starters": definition_starters,
+ }
+ if file:
+ request.update({"file": file})
+ super().request(request)
diff --git a/salve/misc.py b/salve/misc.py
index d70b792..0949244 100644
--- a/salve/misc.py
+++ b/salve/misc.py
@@ -1,9 +1,3 @@
-from multiprocessing.queues import Queue as GenericQueueClass
-from pathlib import Path
-from typing import TYPE_CHECKING, NotRequired, TypedDict
-
-from token_tools import Token
-
COMMANDS: list[str] = [
"autocomplete",
"replacements",
@@ -20,51 +14,3 @@
EDITORCONFIG: COMMAND = COMMANDS[3]
DEFINITION: COMMAND = COMMANDS[4]
LINKS_AND_CHARS: COMMAND = COMMANDS[5]
-
-
-class Message(TypedDict):
- """Base class for messages in and out of the server"""
-
- id: int
- type: str # Can be "request", "response", "notification"
-
-
-class Request(Message):
- """Request results/output from the server with command specific input"""
-
- command: str # Can only be commands in COMMANDS
- file: str
- expected_keywords: NotRequired[list[str]] # autocomplete, replacements
- current_word: NotRequired[str] # autocomplete, replacements, definition
- language: NotRequired[str] # highlight
- text_range: NotRequired[tuple[int, int]] # highlight, links_and_chars
- file_path: NotRequired[Path | str] # editorconfig
- definition_starters: NotRequired[
- list[tuple[str, str]]
- ] # definition (list of regexes)
-
-
-class Notification(Message):
- """Notifies the server to add/update/remove a file for usage in fulfilling commands"""
-
- file: str
- remove: bool
- contents: NotRequired[str]
-
-
-class Response(Message):
- """Server responses to requests and notifications"""
-
- cancelled: bool
- command: NotRequired[str]
- result: NotRequired[list[str | Token] | dict[str, str] | Token]
-
-
-if TYPE_CHECKING:
- ResponseQueueType = GenericQueueClass[Response]
- RequestQueueType = GenericQueueClass[Request | Notification]
-# Else, this is CPython < 3.12. We are now in the No Man's Land
-# of Typing. In this case, avoid subscripting "GenericQueue". Ugh.
-else:
- ResponseQueueType = GenericQueueClass
- RequestQueueType = GenericQueueClass
diff --git a/salve/server.py b/salve/server.py
deleted file mode 100644
index 5a83b2c..0000000
--- a/salve/server.py
+++ /dev/null
@@ -1,205 +0,0 @@
-from logging import Logger
-from multiprocessing.queues import Queue as GenericClassQueue
-from time import sleep
-
-from pyeditorconfig import get_config
-from token_tools import Token, normal_text_range
-
-from .misc import (
- COMMANDS,
- Notification,
- Request,
- RequestQueueType,
- Response,
- ResponseQueueType,
-)
-from .server_functions import (
- find_autocompletions,
- get_definition,
- get_highlights,
- get_replacements,
- get_special_tokens,
-)
-
-
-class Server:
- """Handles input from the user and returns output from special functions. Not an external API."""
-
- def __init__(
- self,
- response_queue: GenericClassQueue,
- requests_queue: GenericClassQueue,
- logger: Logger,
- ) -> None:
- self.logger: Logger = logger
- self.logger.info("Starting server setup")
- self.response_queue: ResponseQueueType = response_queue
- self.requests_queue: RequestQueueType = requests_queue
- self.all_ids: list[int] = []
- self.newest_ids: dict[str, int] = {}
- self.newest_requests: dict[str, Request | None] = {}
- for command in COMMANDS:
- self.newest_ids[command] = 0
- self.newest_requests[command] = None
-
- self.files: dict[str, str] = {}
-
- self.logger.info("Server setup complete")
-
- while True:
- self.run_tasks()
- sleep(0.0025)
-
- def simple_id_response(self, id: int, cancelled: bool = True) -> None:
- self.logger.debug(f"Creating simple response for id {id}")
- response: Response = {
- "id": id,
- "type": "response",
- "cancelled": cancelled,
- }
- self.logger.debug(f"Sending simple response for id {id}")
- self.response_queue.put(response)
- self.logger.info(f"Simple response for id {id} sent")
-
- def parse_line(self, message: Request | Notification) -> None:
- self.logger.debug("Parsing Message from user")
- id: int = message["id"]
- match message["type"]:
- case "notification":
- self.logger.debug("Mesage is of type notification")
- file: str = message["file"] # type: ignore
- if message["remove"]: # type: ignore
- self.logger.info(f"File {file} was requested for removal")
- self.files.pop(file)
- self.logger.info(f"File {file} has been removed")
- return
- contents: str = message["contents"] # type: ignore
- self.files[file] = contents
- self.logger.info(
- f"File {file} has been updated with new contents"
- )
- self.simple_id_response(id, False)
- self.logger.debug(
- f"Notification response for id {id} has been sent"
- )
- case "request":
- self.logger.info(f"Mesage with id {id} is of type request")
- self.all_ids.append(id)
- command: str = message["command"] # type: ignore
- self.newest_ids[command] = id
- self.newest_requests[command] = message # type: ignore
- self.logger.debug("Request stored for parsing")
- case _:
- self.logger.warning(
- f"Unknown type {type}. Sending simple response"
- )
- self.simple_id_response(id)
- self.logger.debug(f"Simple response for id {id} sent")
-
- def cancel_all_ids_except_newest(self) -> None:
- self.logger.info("Cancelling all old id's")
- ids = [
- id["id"]
- for id in list(self.newest_requests.values())
- if id is not None
- ]
- for id in self.all_ids:
- if id in ids:
- self.logger.debug(f"Id {id} is newest of its command")
- continue
- self.logger.debug(
- f"Id {id} is an old request, sending simple respone"
- )
- self.simple_id_response(id)
-
- self.all_ids = []
- self.logger.debug("All ids list reset")
-
- def handle_request(self, request: Request) -> None:
- command: str = request["command"]
- id: int = self.newest_ids[command]
- file: str = request["file"]
- result: list[str | Token] | dict[str, str] = []
- cancelled: bool = False
-
- match request["command"]:
- case "autocomplete":
- self.logger.info("Finding completions for request")
- result = find_autocompletions(
- full_text=self.files[file],
- expected_keywords=request["expected_keywords"], # type: ignore
- current_word=request["current_word"], # type: ignore
- )
- case "replacements":
- self.logger.info("Getting replacements for request")
- result = get_replacements(
- full_text=self.files[file],
- expected_keywords=request["expected_keywords"], # type: ignore
- replaceable_word=request["current_word"], # type: ignore
- )
- case "highlight":
- self.logger.info("Getting normal highlights for request")
- pre_refined_result: list[Token] = get_highlights(
- full_text=self.files[file],
- language=request["language"], # type: ignore
- text_range=request["text_range"], # type: ignore
- )
- result.extend([token for token in pre_refined_result])
- case "editorconfig":
- self.logger.info("Getting editorconfig info for request")
- result = get_config(request["file_path"]) # type: ignore
- case "definition":
- self.logger.info("Getting definition for request")
- result = get_definition(
- self.files[file],
- request["definition_starters"], # type: ignore
- request["current_word"], # type: ignore
- )
- case "links_and_chars":
- self.logger.info("Searching for Links and chars")
- result = get_special_tokens(
- self.files[file],
- normal_text_range(self.files[file], request["text_range"])[ # type: ignore
- 1
- ],
- )
- case _:
- self.logger.warning(f"Command {command} not recognized")
- cancelled = True
-
- response: Response = {
- "id": id,
- "type": "response",
- "cancelled": cancelled,
- "command": command,
- "result": result,
- }
- self.logger.debug("Response created")
- self.response_queue.put(response)
- self.newest_ids[command] = 0
- self.logger.info(f"Response sent for request of command {command}")
-
- def run_tasks(self) -> None:
- if self.requests_queue.empty():
- return
-
- self.logger.debug("New request in queue")
- while not self.requests_queue.empty():
- self.logger.debug("Parsing request")
- self.parse_line(self.requests_queue.get())
-
- if not self.all_ids:
- self.logger.debug("All requests were notifications")
-
- self.logger.debug("Cancelling all old id's")
- self.cancel_all_ids_except_newest()
-
- # Actual work
- for request in list(self.newest_requests.values()):
- if request is None:
- continue
- command: str = request["command"]
- self.logger.info(f"Handling request of command {command}")
- self.handle_request(request)
- self.newest_requests[command] = None
- self.logger.debug("Request completed")
diff --git a/salve/wrappers.py b/salve/wrappers.py
new file mode 100644
index 0000000..a8763c2
--- /dev/null
+++ b/salve/wrappers.py
@@ -0,0 +1,56 @@
+from collegamento import Request
+from pyeditorconfig import get_config
+from token_tools import Token, normal_text_range
+
+from .server_functions import (
+ find_autocompletions,
+ get_definition,
+ get_highlights,
+ get_replacements,
+ get_special_tokens,
+)
+
+
+def find_autocompletions_request_wrapper(request: Request) -> list[str]:
+ return find_autocompletions(
+ full_text=request["file"], # type: ignore
+ expected_keywords=request["expected_keywords"], # type: ignore
+ current_word=request["current_word"], # type: ignore
+ )
+
+
+def get_replacements_request_wrapper(request: Request) -> list[str]:
+ return get_replacements(
+ full_text=request["file"], # type: ignore
+ expected_keywords=request["expected_keywords"], # type: ignore
+ replaceable_word=request["current_word"], # type: ignore
+ )
+
+
+def get_highlights_request_wrapper(request: Request) -> list[Token]:
+ return get_highlights(
+ full_text=request["file"], # type: ignore
+ language=request["language"], # type: ignore
+ text_range=request["text_range"], # type: ignore
+ )
+
+
+def editorconfig_request_wrapper(request: Request) -> dict:
+ return get_config(request["file_path"]) # type: ignore
+
+
+def get_definition_request_wrapper(request: Request) -> Token:
+ return get_definition(
+ request["file"], # type: ignore
+ request["definition_starters"], # type: ignore
+ request["current_word"], # type: ignore
+ )
+
+
+def get_special_tokens_request_wrapper(request: Request) -> list[Token]:
+ return get_special_tokens(
+ request["file"], # type: ignore
+ normal_text_range(request["file"], request["text_range"])[ # type: ignore
+ 1
+ ],
+ )
diff --git a/setup.py b/setup.py
index 8f67330..71d3055 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
setup(
name="salve",
- version="1.0.0",
+ version="1.1.0",
description="Salve is an IPC library that can be used by code editors to easily get autocompletions, replacements, editorconfig suggestions, definitions, and syntax highlighting.",
author="Moosems",
author_email="moosems.j@gmail.com",