forked from python-lsp/python-lsp-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_pylint_lint.py
146 lines (110 loc) · 5.17 KB
/
test_pylint_lint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Copyright 2018 Google LLC.
# Copyright 2017-2020 Palantir Technologies, Inc.
# Copyright 2021- Python Language Server Contributors.
import contextlib
import os
import sys
import tempfile
from test import py2_only, py3_only, IS_PY3
from pylsp import lsp, uris
from pylsp.workspace import Document
from pylsp.plugins import pylint_lint
DOC_URI = uris.from_fs_path(__file__)
DOC = """import sys
def hello():
\tpass
import json
"""
DOC_SYNTAX_ERR = """def hello()
pass
"""
@contextlib.contextmanager
def temp_document(doc_text, workspace):
try:
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
name = temp_file.name
temp_file.write(doc_text)
yield Document(uris.from_fs_path(name), workspace)
finally:
os.remove(name)
def write_temp_doc(document, contents):
with open(document.path, 'w', encoding='utf-8') as temp_file:
temp_file.write(contents)
def test_pylint(config, workspace):
with temp_document(DOC, workspace) as doc:
diags = pylint_lint.pylsp_lint(config, doc, True)
msg = '[unused-import] Unused import sys'
unused_import = [d for d in diags if d['message'] == msg][0]
assert unused_import['range']['start'] == {'line': 0, 'character': 0}
assert unused_import['severity'] == lsp.DiagnosticSeverity.Warning
if IS_PY3:
# test running pylint in stdin
config.plugin_settings('pylint')['executable'] = 'pylint'
diags = pylint_lint.pylsp_lint(config, doc, True)
msg = 'Unused import sys (unused-import)'
unused_import = [d for d in diags if d['message'] == msg][0]
assert unused_import['range']['start'] == {
'line': 0,
'character': 0,
}
assert unused_import['severity'] == lsp.DiagnosticSeverity.Warning
@py3_only
def test_syntax_error_pylint_py3(config, workspace):
with temp_document(DOC_SYNTAX_ERR, workspace) as doc:
diag = pylint_lint.pylsp_lint(config, doc, True)[0]
if sys.version_info[:2] >= (3, 10):
assert diag['message'].count("[syntax-error] expected ':'")
else:
assert diag['message'].startswith('[syntax-error] invalid syntax')
# Pylint doesn't give column numbers for invalid syntax.
assert diag['range']['start'] == {'line': 0, 'character': 12}
assert diag['severity'] == lsp.DiagnosticSeverity.Error
# test running pylint in stdin
config.plugin_settings('pylint')['executable'] = 'pylint'
diag = pylint_lint.pylsp_lint(config, doc, True)[0]
assert diag['message'].count("expected ':'") or diag['message'].startswith('invalid syntax')
# Pylint doesn't give column numbers for invalid syntax.
assert diag['range']['start'] == {'line': 0, 'character': 12}
assert diag['severity'] == lsp.DiagnosticSeverity.Error
@py2_only
def test_syntax_error_pylint_py2(config, workspace):
with temp_document(DOC_SYNTAX_ERR, workspace) as doc:
diag = pylint_lint.pylsp_lint(config, doc, True)[0]
assert diag['message'].startswith('[syntax-error] invalid syntax')
# Pylint doesn't give column numbers for invalid syntax.
assert diag['range']['start'] == {'line': 0, 'character': 0}
assert diag['severity'] == lsp.DiagnosticSeverity.Error
def test_lint_free_pylint(config, workspace):
# Can't use temp_document because it might give us a file that doesn't
# match pylint's naming requirements. We should be keeping this file clean
# though, so it works for a test of an empty lint.
assert not pylint_lint.pylsp_lint(
config, Document(uris.from_fs_path(__file__), workspace), True)
def test_lint_caching(workspace):
# Pylint can only operate on files, not in-memory contents. We cache the
# diagnostics after a run so we can continue displaying them until the file
# is saved again.
#
# We use PylintLinter.lint directly here rather than pylsp_lint so we can
# pass --disable=invalid-name to pylint, since we want a temporary file but
# need to ensure that pylint doesn't give us invalid-name when our temp
# file has capital letters in its name.
flags = '--disable=invalid-name'
with temp_document(DOC, workspace) as doc:
# Start with a file with errors.
diags = pylint_lint.PylintLinter.lint(doc, True, flags)
assert diags
# Fix lint errors and write the changes to disk. Run the linter in the
# in-memory mode to check the cached diagnostic behavior.
write_temp_doc(doc, '')
assert pylint_lint.PylintLinter.lint(doc, False, flags) == diags
# Now check the on-disk behavior.
assert not pylint_lint.PylintLinter.lint(doc, True, flags)
# Make sure the cache was properly cleared.
assert not pylint_lint.PylintLinter.lint(doc, False, flags)
def test_per_file_caching(config, workspace):
# Ensure that diagnostics are cached per-file.
with temp_document(DOC, workspace) as doc:
assert pylint_lint.pylsp_lint(config, doc, True)
assert not pylint_lint.pylsp_lint(
config, Document(uris.from_fs_path(__file__), workspace), False)