-
-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a LanguageClient
autogenerated from lsprotocol
type definitions
#328
Conversation
Always the visionary! I don't think this is as big a change as the Files Changed count makes out? Currently it just affects the client, which is currently only used for testing? But it is of course also laying the groundwork for a similar approach to the server, both in terms of autogeneration and introducing So a few questions that come to mind:
|
The bulk of the files changed are in e240cc7 which is just tweaking the test suite to make use of the new client.
Pre v1, pygls didn't parse server responses into objects so I was originally doing the conversion in pytest-lsp manually. Thanks to the
Now that
Sorry about that 😬, I have my editor setup to auto format files and since this was just a draft, I hadn't gone around and cleaned up the formatting yet. I'd be happy to go with black - maybe in combination with |
Great, thank you. I feel I've got a better grasp on this now. It clearly feels like a logical step for the post-v1, lsprotocol-enabled Pygls. We get better testing and better code discoverability. Regarding lsprotocol pinning, it's only testing against the latest Pygls right? So we do indeed have the guarantee that latest Pygls always works against latest lsprotocol. But of course Pygls-based LSs might be pinning to a particular pygls version, where Pygls itself is pulling in the latest lsprotocol. Unless of course the LS is using some kind of lock file. So yes I think the odds of incompatibilities are lower now, but I wonder if the downsides of breakage because of version incompatibilities are worse than the downsides of pinning against lsprotocol (namely; having to release Pygls more often and losing out on automatically included improvements)? Don't stress too much about the formatting right now. I'll look into Black and isort at some point. |
8475724
to
d164ebf
Compare
I've managed to revert most of the formatting only changes - it should be a lot more obvious what's actually changed now :)
Personally, I think it would be a mistake to introduce anything stronger than a lower bound on the version number of
This. |
Nice work on reverting the formatting changes! I wouldn't have held it against you if they'd remained. But still thanks 🙇 I actually thought a whole lot about your arguments against version pinning, and ended up writing a mini essay 🤓 #331 Long story short: I'm happy not to pin. |
86b376c
to
000f7e8
Compare
This introduces a base `Client` class that the `LanguageClient` and other JSON-RPC based clients can subclass. Currently only stdio communication is implemented. The client uses an asyncio subprocess to launch and communicate with the server.
This commit introduces an example server that implements code actions. Additionally, using the new `LanguageClient` our first true end to end test is introduced.
I rewrote this method to be based on Also by using an asyncio subprocess, we get async readers/writers for stdout/stdin - removing the need for the thread pool!
I've reverted that and instead opted for a different approach that I hope makes sense :) This commit introduces a new example language server! This server is then tested with what I think is pygls' first true end-to-end test, driven by the new What I'm thinking is that we can slowly start introducing end-to-end tests covering parts of the LSP spec, while simultaneously building up a set of concrete examples of how each part of the spec works. The one downside is that these end-to-end tests have to be skipped in pyodide since the architecture of the test runner won't work for that use-case, but hopefully we can fix that at some pointTM |
So we have server: left = int(match.group(1))
right = int(match.group(2))
answer = left + right And a real client that tests that server! assert fix.new_text == "1 + 1 = 2!" This is so good. Thank you so much for this. I think it's great for testing and implicit "documentation". Every test basically becomes a readable example now 🤓 So next time I have to write or touch a test, I'll upgrade it to the new way. And great work with the async stuff, it's not a huge amount of line changes, but a huge amount of investigating went into it. |
Description (e.g. "Related to ...", etc.)
This is something I'd originally put together for
pytest-lsp
but thought it was probably useful enough to try upstreaming intopygls
🙂gen_client.py
script that will autogenerate aLanguageClient
inpygls/lsp/client.py
based on the type definitions inlsprotocol
. It can easily be run via tox -$ tox -e generate
LanguageClient
is based on a new baseClient
class that currently only implements astart_io
method.LanguageClient
I'm also hoping this PR can help move the discussion forward in #306, perhaps even agreeing on pattern we can use for a new, autogenerated base server class? Obviously there's more logic to a server which we won't be able to generate, but we should at least be able to automate the boilerplate method definitions etc.
I'm also using the new base client in
pygls/client.py
as an opportunity to try the higher levelasyncio
APIs which should allow us to simplify some of the code inpygls/server.py
Let me know your thoughts 😄
Code review checklist (for code reviewer to complete)