Skip to main content

Sans-IO pattern, language server protocol implementation

Project description

Language Server Protocol implementation in sans-io pattern. Which is highly inspired by [[https://sans-io.readthedocs.io/how-to-sans-io.html][Sans-IO pattern]]. And some relatived projects: [[https://github.com/python-hyper/hyper-h2][hyper-h2]], [[https://github.com/python-hyper/h11][h11]]

So the actual language server can build on this, it can be integreted with trio, asyncio, or some other frameworks.

* Required python version
Python >= 3.6

* How to install it
There are two ways to install lsp:
- install via pip (recommended)
#+BEGIN_SRC shell
pip install lsp
#+END_SRC
- install via setup.py
#+BEGIN_SRC shell
python setup.py install
#+END_SRC
* Basic Usage example
** For client
#+BEGIN_SRC python
import socket
from lsp import Connection, NEED_DATA, DataReceived, MessageEnd

sock = socket.socket()

sock.connect(("localhost", 10001))
conn = Connection("client")


answer = input("Send request?(y/n)")
while answer == "y":
# use connection send_json method to convert json object to bytes
request_data = conn.send_json({"method": "didOpen"})
# then we can send data to server
sock.sendall(request_data)

while True:
# and then we can get next_event of connection, it can indicate
# that what should we do.
event = conn.next_event()
# we need to receive data from server
if event is NEED_DATA:
try:
data = sock.recv(1024)
except ConnectionResetError:
print('The server connection is closed, So I will leave:)')
conn.close()
sock.close()
exit(0)
else:
print("return from sock.recv")
conn.receive(data)
# we have receive data from server
elif isinstance(event, DataReceived):
print("Receive event, content:")
print(event)
elif isinstance(event, MessageEnd):
print("Server sending data complete.")
break

# then we can call get_received_data() to extract out what we get
header, response_body = conn.get_received_data()
print("Response header from server:")
print(header)
print("Response body from server:")
print(response_body)
answer = input("Send request?(y/n)")
conn.go_next_circle()

#+END_SRC

For more usage example, please check out files in *examples/clients* folder.
** For server
#+BEGIN_SRC python
import socket
from lsp import Connection, NEED_DATA, RequestReceived, DataReceived, MessageEnd

sock = socket.socket()
sock.bind(("0.0.0.0", 10001))
sock.listen(1)
client_sock, addr = sock.accept()
print(f"get connection from {client_sock}")

conn = Connection("server")
try:
while True:
while True:
# call next event to indicate what server socket should do.
event = conn.next_event()

# no data coming yet, so the return value is NEED_DATA
if event is NEED_DATA:
data = client_sock.recv(1024)
if data == b"":
print("Client connection is closed, I will exit.")
exit(0)
conn.receive(data)
# Request header is coming :)
elif isinstance(event, RequestReceived):
print("Receive request header")
print(event.to_data())
# Request data is coming :)
elif isinstance(event, DataReceived):
print("Receive request data")
print(event.to_data())
# client has send data completely.
elif isinstance(event, MessageEnd):
print("Data receive complete:)")
break

# so we can call con.get_received_data to fetch what client send.
received_data = conn.get_received_data()
print(f"Receiving data: {received_data}")

# send response back to client.
print(f"Sending response to client")
data = conn.send_json({"Content": "I am received:)"})
client_sock.sendall(data)
print(f"For now, go to next circle")

# then we need to call go_next_circle, to get another request from client.
conn.go_next_circle()
finally:
sock.close()

#+END_SRC

For more usage example, please check out files in *examples/servers* folder.


* Main API
1. Want to send json data? You can try =conn.send_json=.
2. Want to know what we should do next? You can try =conn.next_event=.
3. After receive data, please don't forget to call =conn.receive(data)=. Which will save data into inner buffer, and it can drive =conn.next_event= method returns other events.

* Main events we will get from next_event
** Client
Client side will get the following values from next_events:
1. NEED_DATA - which indicate that we need to receive data from server.
2. ResponseReceived - Client have receive response header.
3. DataReceived - Client have receive resposne body.
4. MessageEnd - Receive data from server complete.

** Server
Server side will get the following values from next_events:
1. NEED_DATA - which indicate that we need to receive data from client.
2. RequestReceived - Client have send request header, and we receive it.
3. DataReceived - Server have receive response body from client.
4. MessageEnd - Client sending request complete.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for lsp, version 0.1.0
Filename, size File type Python version Upload date Hashes
Filename, size lsp-0.1.0-py3.7.egg (26.2 kB) File type Egg Python version 3.7 Upload date Hashes View
Filename, size lsp-0.1.0.tar.gz (11.7 kB) File type Source Python version None Upload date Hashes View

Supported by

Pingdom Pingdom Monitoring Google Google Object Storage and Download Analytics Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page