python-lsp / python-lsp-server

Fork of the python-language-server project, maintained by the Spyder IDE team and the community
MIT License
1.75k stars 187 forks source link

Method `textDocument/formatting` returning `AttributeError: 'NoneType' object has no attribute 'get_document'` #567

Open ElliotRoe opened 4 weeks ago

ElliotRoe commented 4 weeks ago

Summary

We are attempting to use the codemirror-languageserver npm package as a client for a remote instance of the python-lsp-server. For the most part, we have been successful and the plugin seamlessly supports autocompletions, linting and syntax checking. Our progress can be found in the demo-project folder of our testing repo.

However, we are struggling to get a simple formatting request to successfully return on a button press. Since the codemirror package has no functionality supporting this, we are just directly sending a formatting request via a websocket following the Microsoft LSP standards. Unfortunately, we're getting a AttributeError: 'NoneType' object has no attribute 'get_document' in response. We are getting the same response for the textDocument/rangeFormatting method as well. Any help would be greatly appreciated, and I'll keep this issue updated as I continue to investigate too. Really, I'm just trying to determine if this is a bug or we are incorrectly using the API. Thanks so much!

Investigation (so far)

Relevant Code Snippets

Below are the relevant code snippets and error messages

Initial Config via Codemirror Language Server Client

const ls = languageServer({
      serverUri,
      rootUri: "file:///home/",
      documentUri: "file:///home/index.py",
      languageId: "python",
      workspaceFolders: [
        {
          uri: "file:///home/",
          name: "root",
        },
      ],
    });

    const startState = EditorState.create({
      doc: "# Write your Python code here",
      extensions: [
        basicSetup,
        ls,
        python(),
        lintGutter(),
        indentationMarkers(),
      ],
    });

JSON Request

const formatRequest = {
      jsonrpc: "2.0",
      id: 1,
      method: "textDocument/formatting",
      params: {
        textDocument: {
          uri: "file:///home/index.py",
        },
        options: {
          tabSize: 4,
          insertSpaces: true,
        },
      },
    };

    wsRef.current.send(JSON.stringify(formatRequest));

Full Logs of AttributeError: 'NoneType' object has no attribute 'get_document' Error Message

2024-06-04 11:28:07 2024-06-04 15:28:07,896 UTC - DEBUG - pylsp.python_lsp - consuming payload and feeding it to LSP handler
2024-06-04 11:28:07 2024-06-04 15:28:07,898 UTC - DEBUG - pylsp_jsonrpc.endpoint - Handling request from client {'jsonrpc': '2.0', 'id': 1, 'method': 'textDocument/formatting', 'params': {'textDocument': {'uri': 'file:///home/index.py'}, 'options': {'tabSize': 4, 'insertSpaces': True}}}
2024-06-04 11:28:07 2024-06-04 15:28:07,899 UTC - DEBUG - pylsp_jsonrpc.endpoint - Executing async request handler <function PythonLSPServer.format_document.<locals>.<lambda> at 0xffffa2f6ade0>
2024-06-04 11:28:07 2024-06-04 15:28:07,900 UTC - ERROR - pylsp_jsonrpc.endpoint - Failed to handle request 1
2024-06-04 11:28:07 Traceback (most recent call last):
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/site-packages/pylsp_jsonrpc/endpoint.py", line 234, in callback
2024-06-04 11:28:07     result = future.result()
2024-06-04 11:28:07              ^^^^^^^^^^^^^^^
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/concurrent/futures/_base.py", line 449, in result
2024-06-04 11:28:07     return self.__get_result()
2024-06-04 11:28:07            ^^^^^^^^^^^^^^^^^^^
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
2024-06-04 11:28:07     raise self._exception
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
2024-06-04 11:28:07     result = self.fn(*self.args, **self.kwargs)
2024-06-04 11:28:07              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/site-packages/pylsp/python_lsp.py", line 421, in <lambda>
2024-06-04 11:28:07     return lambda: self._hook("pylsp_format_document", doc_uri, options=options)
2024-06-04 11:28:07                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-06-04 11:28:07   File "/usr/local/lib/python3.11/site-packages/pylsp/python_lsp.py", line 252, in _hook
2024-06-04 11:28:07     doc = workspace.get_document(doc_uri) if doc_uri else None
2024-06-04 11:28:07           ^^^^^^^^^^^^^^^^^^^^^^
2024-06-04 11:28:07 AttributeError: 'NoneType' object has no attribute 'get_document'
2024-06-04 11:28:07 2024-06-04 15:28:07,903 UTC - DEBUG - asyncio - Using selector: EpollSelector
2024-06-04 11:28:07 2024-06-04 15:28:07,903 UTC - DEBUG - websockets.server - > TEXT '{"jsonrpc":"2.0","id":1,"error":{"code":-32602,...^^^^^^^^^^^^^^^\\n"]}}}' [1274 bytes]

Successful textDocument/didChange method log

2024-06-04 11:28:06 2024-06-04 15:28:06,597 UTC - DEBUG - pylsp.python_lsp - consuming payload and feeding it to LSP handler
2024-06-04 11:28:06 2024-06-04 15:28:06,597 UTC - DEBUG - pylsp_jsonrpc.endpoint - Handling notification from client {'jsonrpc': '2.0', 'method': 'textDocument/didChange', 'params': {'textDocument': {'uri': 'file:///home/index.py', 'version': 19}, 'contentChanges': [{'text': '"Please for the love of god format"'}]}}
2024-06-04 11:28:07 2024-06-04 15:28:07,103 UTC - DEBUG - pylsp.config.config -   pylsp_lint [hook]
2024-06-04 11:28:07       config: <pylsp.config.config.Config object at 0xffffaa594110>
2024-06-04 11:28:07       workspace: <pylsp.workspace.Workspace object at 0xffffaa626190>
2024-06-04 11:28:07       document: file:///home/index.py
2024-06-04 11:28:07       is_saved: False
2024-06-04 11:28:07
ccordoba12 commented 3 weeks ago

Hey @ElliotRoe, thanks for reporting. Quick question because I didn't see it mentioned in your message: did you send a didOpen request before sending the formatting one?

If the document was not added to the workspace, that could be the cause of your error.

ElliotRoe commented 3 weeks ago

Hi @ccordoba12 ! Thanks for your response. Looking through the code, the codemirror language server client plugin does send a textDocument/didOpen request upon codemirror component initialization (see their code here). This was also confirmed via logs as I found a successful didOpen notification and several didChange notifications before the above error's timestamp. I included a sample of both occurring before the error timestamp in the logs below.

Sample Logs

didOpen notification

2024-06-04 11:27:55 2024-06-04 15:27:55,669 UTC - DEBUG - pylsp_jsonrpc.endpoint - Handling notification from client {'jsonrpc': '2.0', 'method': 'textDocument/didOpen', 'params': {'textDocument': {'uri': 'file:///home/index.py', 'languageId': 'python', 'text': '# Write your Python code here', 'version': 0}}}

didChange notification

2024-06-04 11:27:58 2024-06-04 15:27:58,720 UTC - DEBUG - pylsp_jsonrpc.endpoint - Handling notification from client {'jsonrpc': '2.0', 'method': 'textDocument/didChange', 'params': {'textDocument': {'uri': 'file:///home/index.py', 'version': 1}, 'contentChanges': [{'text': '"# Write your Python code here"'}]}}

Full logs here:

py-lsp.log

ccordoba12 commented 3 weeks ago

Sorry, I don't know what happens. It seems either the document is not registered in the workspace or the initial workspace is not registered as expected.