Skip to content

Commit 1489e85

Browse files
committed
Depend on python-lsp-server
Palantir's python-language-server is now unmaintained. python-lsp-server is a community-maintained fork.
1 parent 6ed04c1 commit 1489e85

File tree

5 files changed

+79
-76
lines changed

5 files changed

+79
-76
lines changed

README.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ Mypy plugin for PYLS
77
.. image:: https://github.com/Richardk2n/pyls-mypy/workflows/Python%20package/badge.svg?branch=master
88
:target: https://github.com/Richardk2n/pyls-mypy/
99

10-
This is a plugin for the Palantir's Python Language Server (https://github.com/palantir/python-language-server)
10+
This is a plugin for the [Python LSP Server](https://github.com/python-lsp/python-lsp-server).
1111

1212
It, like mypy, requires Python 3.6 or newer.
1313

1414

1515
Installation
1616
------------
1717

18-
Install into the same virtualenv as pyls itself.
18+
Install into the same virtualenv as python-lsp-server itself.
1919

2020
``pip install mypy-ls``
2121

@@ -31,7 +31,7 @@ Depending on your editor, the configuration (found in a file called mypy-ls.cfg
3131
::
3232

3333
{
34-
"enabled": True,
35-
"live_mode": True,
36-
"strict": False
34+
"enabled": True,
35+
"live_mode": True,
36+
"strict": False
3737
}

mypy_ls/plugin.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
"""
3-
File that contains the pyls plugin mypy-ls.
3+
File that contains the pylsp plugin mypy-ls.
44
55
Created on Fri Jul 10 09:53:57 2020
66
@@ -12,9 +12,9 @@
1212
import os.path
1313
import logging
1414
from mypy import api as mypy_api
15-
from pyls import hookimpl
16-
from pyls.workspace import Document, Workspace
17-
from pyls.config.config import Config
15+
from pylsp import hookimpl
16+
from pylsp.workspace import Document, Workspace
17+
from pylsp.config.config import Config
1818
from typing import Optional, Dict, Any, IO, List
1919
import atexit
2020

@@ -27,7 +27,9 @@
2727
tmpFile: Optional[IO[str]] = None
2828

2929

30-
def parse_line(line: str, document: Optional[Document] = None) -> Optional[Dict[str, Any]]:
30+
def parse_line(
31+
line: str, document: Optional[Document] = None
32+
) -> Optional[Dict[str, Any]]:
3133
"""
3234
Return a language-server diagnostic from a line of the Mypy error report.
3335
@@ -54,51 +56,53 @@ def parse_line(line: str, document: Optional[Document] = None) -> Optional[Dict[
5456
if file_path != "<string>": # live mode
5557
# results from other files can be included, but we cannot return
5658
# them.
57-
if document and document.path and not document.path.endswith(
58-
file_path):
59-
log.warning("discarding result for %s against %s", file_path,
60-
document.path)
59+
if document and document.path and not document.path.endswith(file_path):
60+
log.warning(
61+
"discarding result for %s against %s", file_path, document.path
62+
)
6163
return None
6264

6365
lineno = int(linenoStr or 1) - 1 # 0-based line number
6466
offset = int(offsetStr or 1) - 1 # 0-based offset
6567
errno = 2
66-
if severity == 'error':
68+
if severity == "error":
6769
errno = 1
6870
diag: Dict[str, Any] = {
69-
'source': 'mypy',
70-
'range': {
71-
'start': {'line': lineno, 'character': offset},
71+
"source": "mypy",
72+
"range": {
73+
"start": {"line": lineno, "character": offset},
7274
# There may be a better solution, but mypy does not provide end
73-
'end': {'line': lineno, 'character': offset + 1}
75+
"end": {"line": lineno, "character": offset + 1},
7476
},
75-
'message': msg,
76-
'severity': errno
77+
"message": msg,
78+
"severity": errno,
7779
}
7880
if document:
7981
# although mypy does not provide the end of the affected range, we
8082
# can make a good guess by highlighting the word that Mypy flagged
81-
word = document.word_at_position(diag['range']['start'])
83+
word = document.word_at_position(diag["range"]["start"])
8284
if word:
83-
diag['range']['end']['character'] = (
84-
diag['range']['start']['character'] + len(word))
85+
diag["range"]["end"]["character"] = diag["range"]["start"][
86+
"character"
87+
] + len(word)
8588

8689
return diag
8790
return None
8891

8992

9093
@hookimpl
91-
def pyls_lint(config: Config, workspace: Workspace, document: Document,
92-
is_saved: bool) -> List[Dict[str, Any]]:
94+
def pylsp_lint(
95+
config: Config, workspace: Workspace, document: Document, is_saved: bool
96+
) -> List[Dict[str, Any]]:
9397
"""
9498
Lints.
9599
96100
Parameters
97101
----------
98102
config : Config
99-
The pyls config.
103+
The pylsp config.
100104
workspace : Workspace
101-
The pyls workspace.
105+
The pylsp workspace.
102106
document : Document
103107
The document to be linted.
104108
is_saved : bool
@@ -110,27 +114,25 @@ def pyls_lint(config: Config, workspace: Workspace, document: Document,
110114
List of the linting data.
111115
112116
"""
113-
settings = config.plugin_settings('mypy-ls')
114-
live_mode = settings.get('live_mode', True)
115-
args = ['--incremental',
116-
'--show-column-numbers',
117-
'--follow-imports', 'silent']
117+
settings = config.plugin_settings("mypy-ls")
118+
live_mode = settings.get("live_mode", True)
119+
args = ["--incremental", "--show-column-numbers", "--follow-imports", "silent"]
118120

119121
global tmpFile
120122
if live_mode and not is_saved and tmpFile:
121123
tmpFile = open(tmpFile.name, "w")
122124
tmpFile.write(document.source)
123125
tmpFile.close()
124-
args.extend(['--shadow-file', document.path, tmpFile.name])
126+
args.extend(["--shadow-file", document.path, tmpFile.name])
125127
elif not is_saved:
126128
return []
127129

128130
if mypyConfigFile:
129-
args.append('--config-file')
131+
args.append("--config-file")
130132
args.append(mypyConfigFile)
131133
args.append(document.path)
132-
if settings.get('strict', False):
133-
args.append('--strict')
134+
if settings.get("strict", False):
135+
args.append("--strict")
134136

135137
report, errors, _ = mypy_api.run(args)
136138

@@ -144,14 +146,14 @@ def pyls_lint(config: Config, workspace: Workspace, document: Document,
144146

145147

146148
@hookimpl
147-
def pyls_settings(config: Config) -> Dict[str, Dict[str, Dict[str, str]]]:
149+
def pylsp_settings(config: Config) -> Dict[str, Dict[str, Dict[str, str]]]:
148150
"""
149151
Read the settings.
150152
151153
Parameters
152154
----------
153155
config : Config
154-
The pyls config.
156+
The pylsp config.
155157
156158
Returns
157159
-------
@@ -187,10 +189,11 @@ def init(workspace: str) -> Dict[str, str]:
187189
configuration = eval(file.read())
188190
global mypyConfigFile
189191
mypyConfigFile = findConfigFile(workspace, "mypy.ini")
190-
if (("enabled" not in configuration or configuration["enabled"])
191-
and ("live_mode" not in configuration or configuration["live_mode"])):
192+
if ("enabled" not in configuration or configuration["enabled"]) and (
193+
"live_mode" not in configuration or configuration["live_mode"]
194+
):
192195
global tmpFile
193-
tmpFile = tempfile.NamedTemporaryFile('w', delete=False)
196+
tmpFile = tempfile.NamedTemporaryFile("w", delete=False)
194197
tmpFile.close()
195198
return configuration
196199

requirements.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
python-language-server>=0.34.0
2-
mypy
1+
future;python_version < '3'
2+
flake8
3+
configparser
4+
python-lsp-server
5+
mypy;python_version >= '3.2'

setup.cfg

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[metadata]
22
name = mypy-ls
33
author = Tom van Ommeren, Richard Kellnberger
4-
description = Mypy linter for the Python Language Server
4+
description = Mypy linter for the Python LSP Server
55
url = https://github.com/Richardk2n/pyls-mypy
66
long_description = file: README.rst
77
license='MIT'
@@ -17,13 +17,13 @@ classifiers =
1717
[options]
1818
python_requires = >= 3.6
1919
packages = find:
20-
install_requires =
21-
python-language-server>=0.34.0
20+
install_requires =
21+
python-lsp-server
2222
mypy
2323

2424

2525
[options.entry_points]
26-
pyls = mypy_ls = mypy_ls.plugin
26+
pylsp = mypy_ls = mypy_ls.plugin
2727

2828
[options.extras_require]
2929
test =

test/test_plugin.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import pytest
22

3-
from pyls.workspace import Workspace, Document
4-
from pyls.config.config import Config
5-
from pyls import uris
3+
from pylsp.workspace import Workspace, Document
4+
from pylsp.config.config import Config
5+
from pylsp import uris
66
from mock import Mock
77
from mypy_ls import plugin
88

@@ -12,10 +12,8 @@
1212
TYPE_ERR_MSG = '"Dict[<nothing>, <nothing>]" has no attribute "append"'
1313

1414
TEST_LINE = 'test_plugin.py:279:8: error: "Request" has no attribute "id"'
15-
TEST_LINE_WITHOUT_COL = ('test_plugin.py:279: '
16-
'error: "Request" has no attribute "id"')
17-
TEST_LINE_WITHOUT_LINE = ('test_plugin.py: '
18-
'error: "Request" has no attribute "id"')
15+
TEST_LINE_WITHOUT_COL = "test_plugin.py:279: " 'error: "Request" has no attribute "id"'
16+
TEST_LINE_WITHOUT_LINE = "test_plugin.py: " 'error: "Request" has no attribute "id"'
1917

2018

2119
@pytest.fixture
@@ -27,7 +25,6 @@ def workspace(tmpdir):
2725

2826

2927
class FakeConfig(object):
30-
3128
def __init__(self):
3229
self._root_path = "C:"
3330

@@ -37,53 +34,53 @@ def plugin_settings(self, plugin, document_path=None):
3734

3835
def test_settings():
3936
config = FakeConfig()
40-
settings = plugin.pyls_settings(config)
37+
settings = plugin.pylsp_settings(config)
4138
assert settings == {"plugins": {"mypy-ls": {}}}
4239

4340

4441
def test_plugin(workspace):
4542
config = FakeConfig()
4643
doc = Document(DOC_URI, workspace, DOC_TYPE_ERR)
4744
workspace = None
48-
plugin.pyls_settings(config)
49-
diags = plugin.pyls_lint(config, workspace, doc, is_saved=False)
45+
plugin.pylsp_settings(config)
46+
diags = plugin.pylsp_lint(config, workspace, doc, is_saved=False)
5047

5148
assert len(diags) == 1
5249
diag = diags[0]
53-
assert diag['message'] == TYPE_ERR_MSG
54-
assert diag['range']['start'] == {'line': 0, 'character': 0}
55-
assert diag['range']['end'] == {'line': 0, 'character': 1}
50+
assert diag["message"] == TYPE_ERR_MSG
51+
assert diag["range"]["start"] == {"line": 0, "character": 0}
52+
assert diag["range"]["end"] == {"line": 0, "character": 1}
5653

5754

5855
def test_parse_full_line(workspace):
5956
doc = Document(DOC_URI, workspace)
6057
diag = plugin.parse_line(TEST_LINE, doc)
61-
assert diag['message'] == '"Request" has no attribute "id"'
62-
assert diag['range']['start'] == {'line': 278, 'character': 7}
63-
assert diag['range']['end'] == {'line': 278, 'character': 8}
58+
assert diag["message"] == '"Request" has no attribute "id"'
59+
assert diag["range"]["start"] == {"line": 278, "character": 7}
60+
assert diag["range"]["end"] == {"line": 278, "character": 8}
6461

6562

6663
def test_parse_line_without_col(workspace):
6764
doc = Document(DOC_URI, workspace)
6865
diag = plugin.parse_line(TEST_LINE_WITHOUT_COL, doc)
69-
assert diag['message'] == '"Request" has no attribute "id"'
70-
assert diag['range']['start'] == {'line': 278, 'character': 0}
71-
assert diag['range']['end'] == {'line': 278, 'character': 1}
66+
assert diag["message"] == '"Request" has no attribute "id"'
67+
assert diag["range"]["start"] == {"line": 278, "character": 0}
68+
assert diag["range"]["end"] == {"line": 278, "character": 1}
7269

7370

7471
def test_parse_line_without_line(workspace):
7572
doc = Document(DOC_URI, workspace)
7673
diag = plugin.parse_line(TEST_LINE_WITHOUT_LINE, doc)
77-
assert diag['message'] == '"Request" has no attribute "id"'
78-
assert diag['range']['start'] == {'line': 0, 'character': 0}
79-
assert diag['range']['end'] == {'line': 0, 'character': 6}
74+
assert diag["message"] == '"Request" has no attribute "id"'
75+
assert diag["range"]["start"] == {"line": 0, "character": 0}
76+
assert diag["range"]["end"] == {"line": 0, "character": 6}
8077

8178

82-
@pytest.mark.parametrize('word,bounds', [('', (7, 8)), ('my_var', (7, 13))])
79+
@pytest.mark.parametrize("word,bounds", [("", (7, 8)), ("my_var", (7, 13))])
8380
def test_parse_line_with_context(monkeypatch, word, bounds, workspace):
8481
doc = Document(DOC_URI, workspace)
85-
monkeypatch.setattr(Document, 'word_at_position', lambda *args: word)
82+
monkeypatch.setattr(Document, "word_at_position", lambda *args: word)
8683
diag = plugin.parse_line(TEST_LINE, doc)
87-
assert diag['message'] == '"Request" has no attribute "id"'
88-
assert diag['range']['start'] == {'line': 278, 'character': bounds[0]}
89-
assert diag['range']['end'] == {'line': 278, 'character': bounds[1]}
84+
assert diag["message"] == '"Request" has no attribute "id"'
85+
assert diag["range"]["start"] == {"line": 278, "character": bounds[0]}
86+
assert diag["range"]["end"] == {"line": 278, "character": bounds[1]}

0 commit comments

Comments
 (0)