From 1fb1cfcbcec058559f30aa66794416718723408e Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Sun, 17 Dec 2023 21:09:59 +0100 Subject: [PATCH 01/14] Add code to connect a python lsp --- src/PanelCode.js | 3 +++ src/langs/python/python.js | 55 ++++++++++++++++++++++++++++++++++++++ src/window.js | 1 + 3 files changed, 59 insertions(+) create mode 100644 src/langs/python/python.js diff --git a/src/PanelCode.js b/src/PanelCode.js index c36b33b3c..f31428ba2 100644 --- a/src/PanelCode.js +++ b/src/PanelCode.js @@ -3,6 +3,7 @@ import GObject from "gi://GObject"; import { setup as setupVala } from "./langs/vala/vala.js"; import { setup as setupJavaScript } from "./langs/javascript/javascript.js"; +import { setup as setupPython } from "./langs/python/python.js" import { settings as global_settings, makeDropdownFlat } from "./util.js"; export default function PanelCode({ @@ -10,6 +11,7 @@ export default function PanelCode({ previewer, document_vala, document_javascript, + document_python, settings, }) { const panel_code = builder.get_object("panel_code"); @@ -53,6 +55,7 @@ export default function PanelCode({ setupVala({ document: document_vala }); setupJavaScript({ document: document_javascript }); + setupPython({ document: document_python }); function switchLanguage() { panel.language = dropdown_code_lang.selected_item?.string; diff --git a/src/langs/python/python.js b/src/langs/python/python.js new file mode 100644 index 000000000..d6ebc0809 --- /dev/null +++ b/src/langs/python/python.js @@ -0,0 +1,55 @@ +import LSPClient from "../../lsp/LSPClient.js"; + +// Initializes the LSP and sets an error handling strategy. +// The document is a reference to the current text in the python section. +export function setup({ document }) { + const { file, code_view } = document; + + const lspc = createLSPClient({ + code_view, + file, + }); + + lspc.start().catch(console.error); +} + +function createLSPClient({ code_view, file }) { + const uri = file.get_uri(); + + const lspc = new LSPClient( + [ + "ruff-lsp", + ], + { + rootUri: file.get_parent().get_uri(), + uri, + languageId: "python3", + buffer: code_view.buffer, + }, + ); + + lspc.connect("exit", () => { + console.debug("python language server exit"); + }); + + lspc.connect("output", (_self, message) => { + console.debug(`python language server OUT:\n${JSON.stringify(message)}`); + }); + + lspc.connect("input", (_self, message) => { + console.debug(`python language server IN:\n${JSON.stringify(message)}`); + }); + + lspc.connect( + "notification::textDocument/publishDiagnostics", + (_self, params) => { + // Check, if the current python file is affected + if (params.uri !== uri) { + return; + } + code_view.handleDiagnostics(params.diagnostics); + }, + ); + + return lspc; +} diff --git a/src/window.js b/src/window.js index 2e78f463d..dd4853a29 100644 --- a/src/window.js +++ b/src/window.js @@ -154,6 +154,7 @@ export default function Window({ application, session }) { previewer, document_vala, document_javascript, + document_python, settings, }); From 338ea0f0c29dcded25bb1794df18f80954a13457 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Sun, 17 Dec 2023 21:51:13 +0100 Subject: [PATCH 02/14] Add _not yet working_ flatpak module for ruff-lsp Generated the module via `flatpak-pip-generator` on my host with python 3.12. When building with this module, it complains about the package `maturin` missing. I suspect, that it is missing due to the difference in python versions. --- build-aux/modules/python-ruff-lsp.json | 49 +++++++++++++++++++++++++ build-aux/re.sonny.Workbench.Devel.json | 1 + 2 files changed, 50 insertions(+) create mode 100644 build-aux/modules/python-ruff-lsp.json diff --git a/build-aux/modules/python-ruff-lsp.json b/build-aux/modules/python-ruff-lsp.json new file mode 100644 index 000000000..856e941fd --- /dev/null +++ b/build-aux/modules/python-ruff-lsp.json @@ -0,0 +1,49 @@ +{ + "name": "python3-ruff-lsp", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"ruff-lsp\" --no-build-isolation" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl", + "sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/b3/0d/cd4a4071c7f38385dc5ba91286723b4d1090b87815db48216212c6c6c30e/cattrs-23.2.3-py3-none-any.whl", + "sha256": "0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/2d/5b/f18eb1823a4cee9bed70cdcc25eed5a75845367c42e63a79010a7c34f8a7/lsprotocol-2023.0.0-py3-none-any.whl", + "sha256": "e85fc87ee26c816adca9eb497bb3db1a7c79c477a11563626e712eaccf926a05" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", + "sha256": "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/36/31/3799444d3f072ffca1a35eb02a48f964384cc13f001125e87d9f0748687b/pygls-1.2.1-py3-none-any.whl", + "sha256": "7dcfcf12b6f15beb606afa46de2ed348b65a279c340ef2242a9a35c22eeafe94" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/50/a9/ec05a652115645c76cc61b8df95a410fe9e30c858d36bbad305010f292ff/ruff-0.1.8.tar.gz", + "sha256": "f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/d4/e0/502d8d919c29312a6d117ec8e80af4c06e9d0f62c9281ba27e65f9fc9409/ruff_lsp-0.0.48-py3-none-any.whl", + "sha256": "21a1c292631f323401362149c2299a7d9cf2b0296af62e8380cf1d23612bae1a" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/b7/f4/6a90020cd2d93349b442bfcb657d0dc91eee65491600b2cb1d388bc98e6b/typing_extensions-4.9.0-py3-none-any.whl", + "sha256": "af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + } + ] +} diff --git a/build-aux/re.sonny.Workbench.Devel.json b/build-aux/re.sonny.Workbench.Devel.json index f5e5ca981..05a512bfa 100644 --- a/build-aux/re.sonny.Workbench.Devel.json +++ b/build-aux/re.sonny.Workbench.Devel.json @@ -45,6 +45,7 @@ "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", "modules/webp-pixbuf-loader.json", + "modules/python-ruff-lsp.json", { "name": "Workbench", "buildsystem": "meson", From 61720e47397a7deeb9a5ea7e16f3505e8cd84c97 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Wed, 20 Dec 2023 17:52:18 +0100 Subject: [PATCH 03/14] Remove ruff-lsp flatpak module It is not working as intendet and we decided to use pylsp instead. --- build-aux/modules/python-ruff-lsp.json | 49 ------------------------- build-aux/re.sonny.Workbench.Devel.json | 1 - 2 files changed, 50 deletions(-) delete mode 100644 build-aux/modules/python-ruff-lsp.json diff --git a/build-aux/modules/python-ruff-lsp.json b/build-aux/modules/python-ruff-lsp.json deleted file mode 100644 index 856e941fd..000000000 --- a/build-aux/modules/python-ruff-lsp.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "python3-ruff-lsp", - "buildsystem": "simple", - "build-commands": [ - "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"ruff-lsp\" --no-build-isolation" - ], - "sources": [ - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/f0/eb/fcb708c7bf5056045e9e98f62b93bd7467eb718b0202e7698eb11d66416c/attrs-23.1.0-py3-none-any.whl", - "sha256": "1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/b3/0d/cd4a4071c7f38385dc5ba91286723b4d1090b87815db48216212c6c6c30e/cattrs-23.2.3-py3-none-any.whl", - "sha256": "0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/2d/5b/f18eb1823a4cee9bed70cdcc25eed5a75845367c42e63a79010a7c34f8a7/lsprotocol-2023.0.0-py3-none-any.whl", - "sha256": "e85fc87ee26c816adca9eb497bb3db1a7c79c477a11563626e712eaccf926a05" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", - "sha256": "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/36/31/3799444d3f072ffca1a35eb02a48f964384cc13f001125e87d9f0748687b/pygls-1.2.1-py3-none-any.whl", - "sha256": "7dcfcf12b6f15beb606afa46de2ed348b65a279c340ef2242a9a35c22eeafe94" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/50/a9/ec05a652115645c76cc61b8df95a410fe9e30c858d36bbad305010f292ff/ruff-0.1.8.tar.gz", - "sha256": "f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/d4/e0/502d8d919c29312a6d117ec8e80af4c06e9d0f62c9281ba27e65f9fc9409/ruff_lsp-0.0.48-py3-none-any.whl", - "sha256": "21a1c292631f323401362149c2299a7d9cf2b0296af62e8380cf1d23612bae1a" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/b7/f4/6a90020cd2d93349b442bfcb657d0dc91eee65491600b2cb1d388bc98e6b/typing_extensions-4.9.0-py3-none-any.whl", - "sha256": "af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" - } - ] -} diff --git a/build-aux/re.sonny.Workbench.Devel.json b/build-aux/re.sonny.Workbench.Devel.json index 05a512bfa..f5e5ca981 100644 --- a/build-aux/re.sonny.Workbench.Devel.json +++ b/build-aux/re.sonny.Workbench.Devel.json @@ -45,7 +45,6 @@ "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", "modules/webp-pixbuf-loader.json", - "modules/python-ruff-lsp.json", { "name": "Workbench", "buildsystem": "meson", From 070e6e7a5e6a7c8869c94dfe8f1c3b1620eb2144 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Wed, 20 Dec 2023 18:10:39 +0100 Subject: [PATCH 04/14] Fix error handling of LSP message reading. LSPs, who exit early, trigger a lot of errors, because they do not send any headers. This patch fixes the access of undefined headers to prevent runtime exceptions. Furthermore, it adds a timeout to not overwhelm the garbage collection sweeping phase of GTK and adds debug output for non-JSON LSP responses. --- src/lsp/LSPClient.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/lsp/LSPClient.js b/src/lsp/LSPClient.js index 633d500fc..18a3e3464 100644 --- a/src/lsp/LSPClient.js +++ b/src/lsp/LSPClient.js @@ -203,20 +203,38 @@ export default class LSPClient { read += bytes.get_size(); } - const str = decoder_utf8.decode(uint8); - return JSON.parse(str); + // When the LSP responds witha non-conformant JSON, + // the message get's logged. + const str = decoder_utf8.decode(uint8).trim(); + try { + return JSON.parse(str); + } catch (e) { + console.debug("LSP responded with:", str); + throw e; + } } // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#baseProtocol async _read() { const headers = await this._read_headers(); - const length = headers["Content-Length"]; - const content = await this._read_content(length); - if (content) { - this._onmessage(content); + // IF the LSP does not send any headers, + // do not try to decode the message. + if(Object.keys(headers).length != 0) { + const length = headers["Content-Length"]; + const content = await this._read_content(length); + if (content) { + this._onmessage(content); + } } + // Wait for a bit before recursively calling _read, so Gargbage Collection + // can catch up. + await new Promise((resolve, _) => { + setTimeout(() => resolve(), 100); + }); + + this._read().catch(console.error); } From 518cad68541e7ef5b1df043ce7517cfb6d130c40 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Wed, 20 Dec 2023 18:18:20 +0100 Subject: [PATCH 05/14] LSPClient.js only wait conditionally. To not slow down the diagnoses, the LSPClient, should only wait for GC, if it doesn't do any message processing. --- src/lsp/LSPClient.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lsp/LSPClient.js b/src/lsp/LSPClient.js index 18a3e3464..93352ab7f 100644 --- a/src/lsp/LSPClient.js +++ b/src/lsp/LSPClient.js @@ -226,15 +226,16 @@ export default class LSPClient { if (content) { this._onmessage(content); } + } else { + // Wait for a bit, before recursively calling _read, so Garbage Collection + // can catch up. + // This only triggers, if there are no header's, so the delay is not really + // relevant. + await new Promise((resolve, _) => { + setTimeout(() => resolve(), 100); + }); } - // Wait for a bit before recursively calling _read, so Gargbage Collection - // can catch up. - await new Promise((resolve, _) => { - setTimeout(() => resolve(), 100); - }); - - this._read().catch(console.error); } From 32f275935b69ff9c79e0184b88a523bb54664509 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Wed, 20 Dec 2023 18:32:01 +0100 Subject: [PATCH 06/14] Change the Python LSP to pylsp As decided, this commit changes the executed LSP to pyslp and adds the missing code to it up. Furthermore, it adds a missing return in the LSP's setup function, which doesn't seem to have triggered any issues, yet. Although, a locally installed version of pylsp, initializes, it doesn't yet work, because it quit's after sending it's firsts message. --- src/langs/python/PythonDocument.js | 7 +++++++ src/langs/python/python.js | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/langs/python/PythonDocument.js b/src/langs/python/PythonDocument.js index 7d936dd5d..2423f4d39 100644 --- a/src/langs/python/PythonDocument.js +++ b/src/langs/python/PythonDocument.js @@ -1,8 +1,15 @@ import Gio from "gi://Gio"; import Document from "../../Document.js"; +import { setup } from "./python.js"; export class PythonDocument extends Document { + constructor(...args) { + super(...args); + + this.lspc = setup({ document: this }); + } + async format() { const code = await formatPythonCode(this.buffer.text); this.code_view.replaceText(code, true); diff --git a/src/langs/python/python.js b/src/langs/python/python.js index d6ebc0809..a5d53b321 100644 --- a/src/langs/python/python.js +++ b/src/langs/python/python.js @@ -10,7 +10,8 @@ export function setup({ document }) { file, }); - lspc.start().catch(console.error); + + return lspc; } function createLSPClient({ code_view, file }) { @@ -18,7 +19,7 @@ function createLSPClient({ code_view, file }) { const lspc = new LSPClient( [ - "ruff-lsp", + "pylsp" ], { rootUri: file.get_parent().get_uri(), From d51c04a320339da78090cd296561b3ea695e27fa Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Thu, 21 Dec 2023 19:05:57 +0100 Subject: [PATCH 07/14] Add pylsp as a python language server This change packages pylsp as a flatpak module, so it can be included in the flatpak. --- .../modules/python-python-lsp-server.json | 69 +++++++++++++++++++ build-aux/re.sonny.Workbench.Devel.json | 1 + 2 files changed, 70 insertions(+) create mode 100644 build-aux/modules/python-python-lsp-server.json diff --git a/build-aux/modules/python-python-lsp-server.json b/build-aux/modules/python-python-lsp-server.json new file mode 100644 index 000000000..28139d740 --- /dev/null +++ b/build-aux/modules/python-python-lsp-server.json @@ -0,0 +1,69 @@ +{ + "name": "python3-python-lsp-server", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"python-lsp-server\"" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/be/4f/1b6eb5a6d92ae52f3798e9fdffd225f1bcd017172bb732743315390a9025/docstring_to_markdown-0.13-py3-none-any.whl", + "sha256": "aa487059d0883e70e54da25c7b230e918d9e4d40f23d6dfaa2b73e4225b2d7dd" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/20/9f/bc63f0f0737ad7a60800bfd472a4836661adae21f9c2535f3957b1e54ceb/jedi-0.19.1-py2.py3-none-any.whl", + "sha256": "e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/05/63/8011bd08a4111858f79d2b09aad86638490d62fbf881c44e434a6dfca87b/parso-0.8.3-py2.py3-none-any.whl", + "sha256": "c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/05/b8/42ed91898d4784546c5f06c60506400548db3f7a4b3fb441cba4e5c17952/pluggy-1.3.0-py3-none-any.whl", + "sha256": "d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/cb/d9/656659d5b5d5f402b2b174cd0ba9bc827e07ce3c0bf88da65424baf64af8/python_lsp_jsonrpc-1.1.2-py3-none-any.whl", + "sha256": "7339c2e9630ae98903fdaea1ace8c47fba0484983794d6aafd0bd8989be2b03c" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/83/49/355783384945708c604f4ad4c773d4ec93bc609b691698e5d8ecfc51d01c/python_lsp_server-1.9.0-py3-none-any.whl", + "sha256": "6b947cf9dc33d7bed9abc936bb173140fcf606b6eb50cf02e27d4cb09f10d3fb" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/6e/54/6f2bdac7117e89a47de4511c9f01732a283457ab1bf856e1e51aa861619e/ujson-5.9.0.tar.gz", + "sha256": "89cc92e73d5501b8a7f48575eeb14ad27156ad092c2e9fc7e3cf949f07e75532" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", + "sha256": "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/0e/a3/b9a8b0adfe672bf0df5901707aa929d30a97ee390ba651910186776746d2/setuptools_scm-8.0.4-py3-none-any.whl", + "sha256": "b47844cd2a84b83b3187a5782c71128c28b4c94cad8bfb871da2784a5cb54c4f" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/b7/f4/6a90020cd2d93349b442bfcb657d0dc91eee65491600b2cb1d388bc98e6b/typing_extensions-4.9.0-py3-none-any.whl", + "sha256": "af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/bb/e1/ed2dd0850446b8697ad28d118df885ad04140c64ace06c4bd559f7c8a94f/setuptools-69.0.2-py3-none-any.whl", + "sha256": "1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/c7/c3/55076fc728723ef927521abaa1955213d094933dc36d4a2008d5101e1af5/wheel-0.42.0-py3-none-any.whl", + "sha256": "177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d" + } + ] +} diff --git a/build-aux/re.sonny.Workbench.Devel.json b/build-aux/re.sonny.Workbench.Devel.json index f5e5ca981..006d83a2b 100644 --- a/build-aux/re.sonny.Workbench.Devel.json +++ b/build-aux/re.sonny.Workbench.Devel.json @@ -45,6 +45,7 @@ "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", "modules/webp-pixbuf-loader.json", + "modules/python-python-lsp-server.json", { "name": "Workbench", "buildsystem": "meson", From d84c66efe3183f3749664ac55543bbf8e95a2485 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Tue, 26 Dec 2023 13:06:08 +0100 Subject: [PATCH 08/14] Actually start pylsp after setting it up. I just forgot this before. --- src/langs/python/python.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/langs/python/python.js b/src/langs/python/python.js index a5d53b321..3e7e9e451 100644 --- a/src/langs/python/python.js +++ b/src/langs/python/python.js @@ -10,6 +10,12 @@ export function setup({ document }) { file, }); + lspc.start().catch(console.error); + + code_view.buffer.connect("modified-changed", () => { + if (!code_view.buffer.get_modified()) return; + lspc.didChange().catch(console.error); + }); return lspc; } @@ -30,14 +36,17 @@ function createLSPClient({ code_view, file }) { ); lspc.connect("exit", () => { + console.log("PYLSP EXIT") console.debug("python language server exit"); }); lspc.connect("output", (_self, message) => { + console.log("PYLSP OUT", message) console.debug(`python language server OUT:\n${JSON.stringify(message)}`); }); lspc.connect("input", (_self, message) => { + console.log("PYLSP IN", message) console.debug(`python language server IN:\n${JSON.stringify(message)}`); }); @@ -48,6 +57,7 @@ function createLSPClient({ code_view, file }) { if (params.uri !== uri) { return; } + console.log("PYLSP DIAG", params) code_view.handleDiagnostics(params.diagnostics); }, ); From b149fab88f1351194fa873fed18cb524ee97cccf Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Tue, 26 Dec 2023 13:16:52 +0100 Subject: [PATCH 09/14] Revert not yet merged changes to the LSPClient --- src/lsp/LSPClient.js | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/lsp/LSPClient.js b/src/lsp/LSPClient.js index 93352ab7f..633d500fc 100644 --- a/src/lsp/LSPClient.js +++ b/src/lsp/LSPClient.js @@ -203,37 +203,18 @@ export default class LSPClient { read += bytes.get_size(); } - // When the LSP responds witha non-conformant JSON, - // the message get's logged. - const str = decoder_utf8.decode(uint8).trim(); - try { - return JSON.parse(str); - } catch (e) { - console.debug("LSP responded with:", str); - throw e; - } + const str = decoder_utf8.decode(uint8); + return JSON.parse(str); } // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#baseProtocol async _read() { const headers = await this._read_headers(); - // IF the LSP does not send any headers, - // do not try to decode the message. - if(Object.keys(headers).length != 0) { - const length = headers["Content-Length"]; - const content = await this._read_content(length); - if (content) { - this._onmessage(content); - } - } else { - // Wait for a bit, before recursively calling _read, so Garbage Collection - // can catch up. - // This only triggers, if there are no header's, so the delay is not really - // relevant. - await new Promise((resolve, _) => { - setTimeout(() => resolve(), 100); - }); + const length = headers["Content-Length"]; + const content = await this._read_content(length); + if (content) { + this._onmessage(content); } this._read().catch(console.error); From 490196beb5d922ae8ba2207090cb3e628df35ed7 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Tue, 26 Dec 2023 13:19:06 +0100 Subject: [PATCH 10/14] Remove overlooked console.log statements in the python LSP file. --- src/langs/python/python.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/langs/python/python.js b/src/langs/python/python.js index 3e7e9e451..7018888fe 100644 --- a/src/langs/python/python.js +++ b/src/langs/python/python.js @@ -36,17 +36,14 @@ function createLSPClient({ code_view, file }) { ); lspc.connect("exit", () => { - console.log("PYLSP EXIT") console.debug("python language server exit"); }); lspc.connect("output", (_self, message) => { - console.log("PYLSP OUT", message) console.debug(`python language server OUT:\n${JSON.stringify(message)}`); }); lspc.connect("input", (_self, message) => { - console.log("PYLSP IN", message) console.debug(`python language server IN:\n${JSON.stringify(message)}`); }); @@ -57,7 +54,6 @@ function createLSPClient({ code_view, file }) { if (params.uri !== uri) { return; } - console.log("PYLSP DIAG", params) code_view.handleDiagnostics(params.diagnostics); }, ); From 490590ffaacb23bf12f5b32e35ed0c29a6da9073 Mon Sep 17 00:00:00 2001 From: Jan Fooken Date: Tue, 26 Dec 2023 14:49:03 +0100 Subject: [PATCH 11/14] Run eslint on python.js and fix formatting --- src/langs/python/python.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/langs/python/python.js b/src/langs/python/python.js index 7018888fe..5d42e8168 100644 --- a/src/langs/python/python.js +++ b/src/langs/python/python.js @@ -23,17 +23,12 @@ export function setup({ document }) { function createLSPClient({ code_view, file }) { const uri = file.get_uri(); - const lspc = new LSPClient( - [ - "pylsp" - ], - { - rootUri: file.get_parent().get_uri(), - uri, - languageId: "python3", - buffer: code_view.buffer, - }, - ); + const lspc = new LSPClient(["pylsp"], { + rootUri: file.get_parent().get_uri(), + uri, + languageId: "python3", + buffer: code_view.buffer, + }); lspc.connect("exit", () => { console.debug("python language server exit"); From b85736e38452c67ca71db3a2a242c9462b5547ef Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Tue, 13 Feb 2024 20:28:07 +0100 Subject: [PATCH 12/14] fix impl --- src/common.js | 5 ++++ src/langs/python/python.js | 57 +++++++++++--------------------------- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/src/common.js b/src/common.js index 2430b7d1b..3dc125b9b 100644 --- a/src/common.js +++ b/src/common.js @@ -109,6 +109,11 @@ export const languages = [ document: null, default_file: "main.py", index: 3, + language_server: ["pylsp", "-v"], + formatting_options: { + ...formatting_options, + tabSize: 4, + }, }, ]; diff --git a/src/langs/python/python.js b/src/langs/python/python.js index 5d42e8168..fc66bdaa8 100644 --- a/src/langs/python/python.js +++ b/src/langs/python/python.js @@ -1,57 +1,32 @@ -import LSPClient from "../../lsp/LSPClient.js"; +import { createLSPClient } from "../../common.js"; +import { getLanguage } from "../../util.js"; -// Initializes the LSP and sets an error handling strategy. -// The document is a reference to the current text in the python section. export function setup({ document }) { - const { file, code_view } = document; + const { file, buffer, code_view } = document; const lspc = createLSPClient({ - code_view, - file, + lang: getLanguage("python"), + root_uri: file.get_parent().get_uri(), + quiet: false, }); - - lspc.start().catch(console.error); - - code_view.buffer.connect("modified-changed", () => { - if (!code_view.buffer.get_modified()) return; - lspc.didChange().catch(console.error); - }); - - return lspc; -} - -function createLSPClient({ code_view, file }) { - const uri = file.get_uri(); - - const lspc = new LSPClient(["pylsp"], { - rootUri: file.get_parent().get_uri(), - uri, - languageId: "python3", - buffer: code_view.buffer, - }); - - lspc.connect("exit", () => { - console.debug("python language server exit"); - }); - - lspc.connect("output", (_self, message) => { - console.debug(`python language server OUT:\n${JSON.stringify(message)}`); - }); - - lspc.connect("input", (_self, message) => { - console.debug(`python language server IN:\n${JSON.stringify(message)}`); - }); - + lspc.buffer = buffer; + lspc.uri = file.get_uri(); lspc.connect( "notification::textDocument/publishDiagnostics", (_self, params) => { - // Check, if the current python file is affected - if (params.uri !== uri) { + if (params.uri !== file.get_uri()) { return; } code_view.handleDiagnostics(params.diagnostics); }, ); + lspc.start().catch(console.error); + + buffer.connect("modified-changed", () => { + if (!buffer.get_modified()) return; + lspc.didChange().catch(console.error); + }); + return lspc; } From 2013ce45a7c2b765c5aab131023edf50eefad618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Capypara=20K=C3=B6pcke?= Date: Sun, 3 Mar 2024 18:17:17 +0100 Subject: [PATCH 13/14] Add pyflakes and rope for basic Python lsp functionality --- build-aux/README.md | 18 +++++++++++------- build-aux/modules/python-pyflakes.json | 14 ++++++++++++++ build-aux/modules/python-rope.json | 24 ++++++++++++++++++++++++ build-aux/re.sonny.Workbench.Devel.json | 2 ++ build-aux/re.sonny.Workbench.json | 3 +++ 5 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 build-aux/modules/python-pyflakes.json create mode 100644 build-aux/modules/python-rope.json diff --git a/build-aux/README.md b/build-aux/README.md index ce9389722..1890574ba 100644 --- a/build-aux/README.md +++ b/build-aux/README.md @@ -14,24 +14,28 @@ cd gst-plugin-gtk4-0.11.1/ # cp generated-sources.json to gst-plugin-gtk4-sources.json ``` -### Python Black Dependency +### Python Modules -`modules/python-black.json` contains the Flatpak modules to install [https://github.com/psf/black](black), the -uncompromising Python code formatter. +The `modules/python-*.json` files contain Flatpak modules to install Python dependencies. -This file is partially auto-generated. Here is how to generate it: +These files are (sometimes partially, see below) auto-generated. Here is how to generate it: 1. Obtain an up-to-date copy of [flatpak-builder-tools](https://github.com/flatpak/flatpak-builder-tools). 2. Make sure you have a Python virtualenv activated with the dependencies for the `pip` generator from the repo above. -3. Run `python3 <...>/flatpak-builder-tools/pip/flatpak-pip-generator black -o modules/python-black --build-isolation` +3. Run `python3 <...>/flatpak-builder-tools/pip/flatpak-pip-generator -o modules/python- --build-isolation` -You will notice that Workbench will now not build. This is due to these issues: +You will notice that Workbench will not build after auto-generating these files as described above. +This is due to these issues: - https://github.com/flatpak/flatpak-builder-tools/issues/380 - https://github.com/pypa/pip/issues/7863 This means that the generated JSON file now needs its build dependencies manually added. Check the build dependencies -of black and their dependencies and add them to the JSON as well. Brute-forcing the build to obtain missing packages +of the package and their dependencies and add them to the JSON as well. Brute-forcing the build to obtain missing packages may help as does referencing old commits of the file. You can also use the generator command to generate dependencies for them and then merge it into the file by hand, but note that you will also need to manually collect their build dependencies too. + +In some cases you may also need to manually remove some packages the generator adds (such as `packaging` with `rope`, +as the SDK and Runtime already contain a version of these packages that can not be replaced. Make sure the package +you want to install is actually compatible with the version of that dependency in the SDK/Runtime. diff --git a/build-aux/modules/python-pyflakes.json b/build-aux/modules/python-pyflakes.json new file mode 100644 index 000000000..51061871c --- /dev/null +++ b/build-aux/modules/python-pyflakes.json @@ -0,0 +1,14 @@ +{ + "name": "python3-pyflakes", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pyflakes\"" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/d4/d7/f1b7db88d8e4417c5d47adad627a93547f44bdc9028372dbd2313f34a855/pyflakes-3.2.0-py2.py3-none-any.whl", + "sha256": "84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a" + } + ] +} diff --git a/build-aux/modules/python-rope.json b/build-aux/modules/python-rope.json new file mode 100644 index 000000000..702789888 --- /dev/null +++ b/build-aux/modules/python-rope.json @@ -0,0 +1,24 @@ +{ + "name": "python3-rope", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"rope\"" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl", + "sha256": "0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/19/4f/e0b94fe3bd8d8b5ba63153465f7930a40d4645b2d161a1a67c7c6612d6cf/pytoolconfig-1.2.6-py3-none-any.whl", + "sha256": "e8b2e538f11dbabc4617884d45401e0105e2d7db920cb8ae6baa94d66126a8e3" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/da/d8/67eab7817826f23a26d2a1442d623c7ce4219e439e3dc7e25fc0bb25d2cb/rope-1.12.0-py3-none-any.whl", + "sha256": "01f06624159e6b2ec9b94412d519e8877a19eeabe392f469c36f7236df05d443" + } + ] +} diff --git a/build-aux/re.sonny.Workbench.Devel.json b/build-aux/re.sonny.Workbench.Devel.json index 5fd4c4d26..5c89ebc7d 100644 --- a/build-aux/re.sonny.Workbench.Devel.json +++ b/build-aux/re.sonny.Workbench.Devel.json @@ -44,6 +44,8 @@ "modules/libspelling.json", "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", + "modules/python-rope.json", + "modules/python-pyflakes.json", "modules/python-python-lsp-server.json", { "name": "Workbench", diff --git a/build-aux/re.sonny.Workbench.json b/build-aux/re.sonny.Workbench.json index af672992d..b3290c974 100644 --- a/build-aux/re.sonny.Workbench.json +++ b/build-aux/re.sonny.Workbench.json @@ -44,6 +44,9 @@ "modules/libspelling.json", "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", + "modules/python-rope.json", + "modules/python-pyflakes.json", + "modules/python-python-lsp-server.json", { "name": "Workbench", "buildsystem": "meson", From a56e18fd3f36942c78caf4f277a954aa727b0faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Capypara=20K=C3=B6pcke?= Date: Sun, 3 Mar 2024 20:13:42 +0100 Subject: [PATCH 14/14] Remove rope again --- build-aux/modules/python-rope.json | 24 ------------------------ build-aux/re.sonny.Workbench.Devel.json | 1 - build-aux/re.sonny.Workbench.json | 1 - 3 files changed, 26 deletions(-) delete mode 100644 build-aux/modules/python-rope.json diff --git a/build-aux/modules/python-rope.json b/build-aux/modules/python-rope.json deleted file mode 100644 index 702789888..000000000 --- a/build-aux/modules/python-rope.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "python3-rope", - "buildsystem": "simple", - "build-commands": [ - "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"rope\"" - ], - "sources": [ - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl", - "sha256": "0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/19/4f/e0b94fe3bd8d8b5ba63153465f7930a40d4645b2d161a1a67c7c6612d6cf/pytoolconfig-1.2.6-py3-none-any.whl", - "sha256": "e8b2e538f11dbabc4617884d45401e0105e2d7db920cb8ae6baa94d66126a8e3" - }, - { - "type": "file", - "url": "https://files.pythonhosted.org/packages/da/d8/67eab7817826f23a26d2a1442d623c7ce4219e439e3dc7e25fc0bb25d2cb/rope-1.12.0-py3-none-any.whl", - "sha256": "01f06624159e6b2ec9b94412d519e8877a19eeabe392f469c36f7236df05d443" - } - ] -} diff --git a/build-aux/re.sonny.Workbench.Devel.json b/build-aux/re.sonny.Workbench.Devel.json index 5c89ebc7d..47d0f720b 100644 --- a/build-aux/re.sonny.Workbench.Devel.json +++ b/build-aux/re.sonny.Workbench.Devel.json @@ -44,7 +44,6 @@ "modules/libspelling.json", "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", - "modules/python-rope.json", "modules/python-pyflakes.json", "modules/python-python-lsp-server.json", { diff --git a/build-aux/re.sonny.Workbench.json b/build-aux/re.sonny.Workbench.json index b3290c974..384caa5e2 100644 --- a/build-aux/re.sonny.Workbench.json +++ b/build-aux/re.sonny.Workbench.json @@ -44,7 +44,6 @@ "modules/libspelling.json", "modules/GTKCssLanguageServer.json", "modules/icon-development-kit.json", - "modules/python-rope.json", "modules/python-pyflakes.json", "modules/python-python-lsp-server.json", {