Skip to content

Commit 2d7e070

Browse files
authored
Merge pull request #13 from finecode-dev/bugfix/lsp-server
Fix integration with IDE after adding execution environments
2 parents 514891d + e0104c1 commit 2d7e070

File tree

18 files changed

+243
-222
lines changed

18 files changed

+243
-222
lines changed

extensions/fine_python_module_exports/fine_python_module_exports/extension.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
# from finecode.extension_runner.interfaces import icache
1515

16+
1617
def uri_str_to_path(uri_str: str) -> Path:
1718
return Path(uri_str.replace("file://", ""))
1819

finecode_extension_runner/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dependencies = [
1111
"click==8.1.*",
1212
"pydantic==2.11.*",
1313
"platformdirs==4.3.*",
14-
"pygls==2.0.0-a2",
14+
"pygls==2.0.0-a6",
1515
"finecode_extension_api==0.3.*",
1616
"deepmerge==2.0.*",
1717
]

finecode_extension_runner/src/finecode_extension_runner/_services/run_action.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,10 @@ async def run_action(
269269
f"R{run_id} | Run action end '{request.action_name}', duration: {duration}ms"
270270
)
271271

272-
if not isinstance(action_result, code_action.RunActionResult):
272+
# if partial results were sent, `action_result` may be None
273+
if action_result is not None and not isinstance(
274+
action_result, code_action.RunActionResult
275+
):
273276
logger.error(
274277
f"R{run_id} | Unexpected result type: {type(action_result).__name__}"
275278
)
@@ -284,7 +287,7 @@ async def run_action(
284287

285288

286289
def action_result_to_run_action_response(
287-
action_result: code_action.RunActionResult,
290+
action_result: code_action.RunActionResult | None,
288291
asked_result_format: typing.Literal["json"] | typing.Literal["string"],
289292
) -> schemas.RunActionResponse:
290293
serialized_result: dict[str, typing.Any] | str | None = None

finecode_extension_runner/src/finecode_extension_runner/lsp_server.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,16 @@ async def update_config(ls: lsp_server.LanguageServer, params):
207207
raise e
208208

209209

210+
def convert_path_keys(
211+
obj: dict[str | pathlib.Path, typing.Any] | list[typing.Any],
212+
) -> dict[str, typing.Any] | list[typing.Any]:
213+
if isinstance(obj, dict):
214+
return {str(k): convert_path_keys(v) for k, v in obj.items()}
215+
elif isinstance(obj, list):
216+
return [convert_path_keys(item) for item in obj]
217+
return obj
218+
219+
210220
class CustomJSONEncoder(json.JSONEncoder):
211221
# add support of serializing pathes to json.dumps
212222
def default(self, obj):
@@ -240,7 +250,11 @@ async def run_action(ls: lsp_server.LanguageServer, params):
240250

241251
# dict key can be path, but pygls fails to handle slashes in dict keys, use strings
242252
# representation of result instead until the problem is properly solved
243-
result_str = json.dumps(response.to_dict()["result"], cls=CustomJSONEncoder)
253+
#
254+
# custom json encoder converts dict values and `convert_path_keys` is used to
255+
# convert dict keys
256+
result_dict = convert_path_keys(response.to_dict()["result"])
257+
result_str = json.dumps(result_dict, cls=CustomJSONEncoder)
244258
return {
245259
"status": status,
246260
"result": result_str,

finecode_extension_runner/src/finecode_extension_runner/schemas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@ class RunActionOptions(BaseSchema):
5252
class RunActionResponse(BaseSchema):
5353
return_code: int
5454
# result can be empty(=None) e.g. if it was sent as a list of partial results
55-
result: dict[str, Any] | None
55+
result: dict[str, Any] | str | None
5656
format: Literal["json"] | Literal["string"] | Literal["styled_text_json"] = "json"

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ dependencies = [
1111
"watchdog==4.0.*",
1212
"click==8.1.*",
1313
"pydantic==2.11.*",
14-
"platformdirs==4.3.*",
15-
"pygls==2.0.0-a2",
14+
"pygls==2.0.0-a6",
1615
"finecode_extension_api==0.3.*",
1716
"finecode_extension_runner==0.3.*",
1817
"ordered-set==4.1.*",

src/finecode/app_dirs.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/finecode/cli_app/dump_config.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
from loguru import logger
55

6-
from finecode import context, services
7-
from finecode.config import config_models, read_configs
6+
from finecode import context, proxy_utils, services
7+
from finecode.config import collect_actions, config_models, read_configs
88
from finecode.runner import manager as runner_manager
99

1010

@@ -40,23 +40,49 @@ async def dump_config(workdir_path: pathlib.Path, project_name: str):
4040
f"Reading project configs(without presets) in {project.dir_path} failed: {exception.message}"
4141
)
4242

43+
# Some tools like IDE extensions for syntax highlighting rely on
44+
# file name. Keep file name of config the same and save in subdirectory
45+
project_dir_path = list(ws_context.ws_projects.keys())[0]
46+
dump_dir_path = project_dir_path / "finecode_config_dump"
47+
dump_file_path = dump_dir_path / "pyproject.toml"
48+
project_def = ws_context.ws_projects[project_dir_path]
49+
actions_by_projects = {project_dir_path: ["dump_config"]}
50+
4351
# start runner to init project config
4452
try:
53+
# reread projects configs, now with resolved presets
54+
# to be able to resolve presets, start runners with presets first
4555
try:
46-
await runner_manager.update_runners(ws_context)
56+
await runner_manager.start_runners_with_presets(
57+
projects=[project_def], ws_context=ws_context
58+
)
4759
except runner_manager.RunnerFailedToStart as exception:
4860
raise DumpFailed(
49-
f"One or more projects are misconfigured, runners for them didn't"
50-
f" start: {exception.message}. Check logs for details."
61+
f"Starting runners with presets failed: {exception.message}"
62+
)
63+
64+
try:
65+
await read_configs.read_project_config(
66+
project=project, ws_context=ws_context
67+
)
68+
collect_actions.collect_actions(
69+
project_path=project.dir_path, ws_context=ws_context
70+
)
71+
except config_models.ConfigurationError as exception:
72+
raise DumpFailed(
73+
f"Rereading project config with presets and collecting actions in {project.dir_path} failed: {exception.message}"
74+
)
75+
76+
try:
77+
await proxy_utils.start_required_environments(
78+
actions_by_projects, ws_context
79+
)
80+
except proxy_utils.StartingEnvironmentsFailed as exception:
81+
raise DumpFailed(
82+
f"Failed to start environments for running 'dump_config': {exception.message}"
5183
)
5284

53-
# Some tools like IDE extensions for syntax highlighting rely on
54-
# file name. Keep file name of config the same and save in subdirectory
55-
project_dir_path = list(ws_context.ws_projects.keys())[0]
56-
dump_dir_path = project_dir_path / "finecode_config_dump"
57-
dump_file_path = dump_dir_path / "pyproject.toml"
5885
project_raw_config = ws_context.ws_projects_raw_configs[project_dir_path]
59-
project_def = ws_context.ws_projects[project_dir_path]
6086

6187
await services.run_action(
6288
action_name="dump_config",

src/finecode/config/read_configs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ async def read_projects_in_dir(
5959
actions=actions,
6060
env_configs={},
6161
)
62+
is_new_project = not def_file.parent in ws_context.ws_projects
6263
ws_context.ws_projects[def_file.parent] = new_project
63-
new_projects.append(new_project)
64+
if is_new_project:
65+
new_projects.append(new_project)
6466
return new_projects
6567

6668

src/finecode/logger_utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import inspect
22
import logging
3+
import sys
34
from pathlib import Path
45

56
from loguru import logger
67

7-
from finecode import app_dirs
88
from finecode_extension_runner import logs
99

1010

1111
def init_logger(trace: bool, stdout: bool = False):
12-
log_dir_path = Path(app_dirs.get_app_dirs().user_log_dir)
12+
venv_dir_path = Path(sys.executable) / ".." / ".."
13+
logs_dir_path = venv_dir_path / "logs"
14+
1315
logger.remove()
1416
# disable logging raw messages
1517
# TODO: make configurable
@@ -20,7 +22,7 @@ def init_logger(trace: bool, stdout: bool = False):
2022
]
2123
)
2224
logs.save_logs_to_file(
23-
file_path=log_dir_path / "execution.log",
25+
file_path=logs_dir_path / "workspace_manager.log",
2426
log_level="TRACE" if trace else "INFO",
2527
stdout=stdout,
2628
)

0 commit comments

Comments
 (0)