10
10
import tempfile
11
11
import os
12
12
import os .path
13
+ from pathlib import Path
13
14
import logging
14
15
from mypy import api as mypy_api
15
16
from pylsp import hookimpl
24
25
log = logging .getLogger (__name__ )
25
26
26
27
# A mapping from workspace path to config file path
27
- mypyConfigFileMap : Dict [str , Optional [str ]] = dict ()
28
+ mypyConfigFileMap : Dict [str , Optional [str ]] = {}
28
29
29
30
tmpFile : Optional [IO [str ]] = None
30
31
33
34
# so store a cache of last diagnostics for each file a-la the pylint plugin,
34
35
# so we can return some potentially-stale diagnostics.
35
36
# https://github.com/python-lsp/python-lsp-server/blob/v1.0.1/pylsp/plugins/pylint_lint.py#L55-L62
36
- last_diagnostics : Dict [str , List ] = collections .defaultdict (list )
37
+ last_diagnostics : Dict [str , List [ Dict [ str , Any ]] ] = collections .defaultdict (list )
37
38
38
39
39
- def parse_line (
40
- line : str , document : Optional [Document ] = None
41
- ) -> Optional [Dict [str , Any ]]:
40
+ def parse_line (line : str , document : Optional [Document ] = None ) -> Optional [Dict [str , Any ]]:
42
41
"""
43
42
Return a language-server diagnostic from a line of the Mypy error report.
44
43
@@ -66,9 +65,7 @@ def parse_line(
66
65
# results from other files can be included, but we cannot return
67
66
# them.
68
67
if document and document .path and not document .path .endswith (file_path ):
69
- log .warning (
70
- "discarding result for %s against %s" , file_path , document .path
71
- )
68
+ log .warning ("discarding result for %s against %s" , file_path , document .path )
72
69
return None
73
70
74
71
lineno = int (linenoStr or 1 ) - 1 # 0-based line number
@@ -91,9 +88,7 @@ def parse_line(
91
88
# can make a good guess by highlighting the word that Mypy flagged
92
89
word = document .word_at_position (diag ["range" ]["start" ])
93
90
if word :
94
- diag ["range" ]["end" ]["character" ] = diag ["range" ]["start" ][
95
- "character"
96
- ] + len (word )
91
+ diag ["range" ]["end" ]["character" ] = diag ["range" ]["start" ]["character" ] + len (word )
97
92
98
93
return diag
99
94
return None
@@ -124,6 +119,21 @@ def pylsp_lint(
124
119
125
120
"""
126
121
settings = config .plugin_settings ("pylsp_mypy" )
122
+ oldSettings1 = config .plugin_settings ("mypy-ls" )
123
+ if oldSettings1 != {}:
124
+ raise DeprecationWarning (
125
+ "Your configuration uses the namespace mypy-ls, this should be changed to pylsp_mypy"
126
+ )
127
+ oldSettings2 = config .plugin_settings ("mypy_ls" )
128
+ if oldSettings2 != {}:
129
+ raise DeprecationWarning (
130
+ "Your configuration uses the namespace mypy_ls, this should be changed to pylsp_mypy"
131
+ )
132
+ if settings == {}:
133
+ settings = oldSettings1
134
+ if settings == {}:
135
+ settings = oldSettings2
136
+
127
137
log .info (
128
138
"lint settings = %s document.path = %s is_saved = %s" ,
129
139
settings ,
@@ -181,9 +191,7 @@ def pylsp_lint(
181
191
# In either case, reset to fresh state
182
192
_ , _err , _status = mypy_api .run_dmypy (["status" ])
183
193
if _status != 0 :
184
- log .info (
185
- "restarting dmypy from status: %s message: %s" , _status , _err .strip ()
186
- )
194
+ log .info ("restarting dmypy from status: %s message: %s" , _status , _err .strip ())
187
195
mypy_api .run_dmypy (["kill" ])
188
196
189
197
# run to use existing daemon or restart if required
@@ -242,19 +250,15 @@ def init(workspace: str) -> Dict[str, str]:
242
250
The plugin config dict.
243
251
244
252
"""
245
- # On windows the path contains \\ on linux it contains / all the code works with /
246
253
log .info ("init workspace = %s" , workspace )
247
- workspace = workspace .replace ("\\ " , "/" )
248
254
249
255
configuration = {}
250
- path = findConfigFile (workspace , "pylsp-mypy.cfg" )
256
+ path = findConfigFile (workspace , [ "pylsp-mypy.cfg" , "mypy-ls.cfg" , "mypy_ls.cfg" ] )
251
257
if path :
252
258
with open (path ) as file :
253
259
configuration = eval (file .read ())
254
260
255
- mypyConfigFile = findConfigFile (workspace , "mypy.ini" )
256
- if not mypyConfigFile :
257
- mypyConfigFile = findConfigFile (workspace , ".mypy.ini" )
261
+ mypyConfigFile = findConfigFile (workspace , ["mypy.ini" , ".mypy.ini" ])
258
262
mypyConfigFileMap [workspace ] = mypyConfigFile
259
263
260
264
if ("enabled" not in configuration or configuration ["enabled" ]) and (
@@ -268,7 +272,7 @@ def init(workspace: str) -> Dict[str, str]:
268
272
return configuration
269
273
270
274
271
- def findConfigFile (path : str , name : str ) -> Optional [str ]:
275
+ def findConfigFile (path : str , names : List [ str ] ) -> Optional [str ]:
272
276
"""
273
277
Search for a config file.
274
278
@@ -279,24 +283,28 @@ def findConfigFile(path: str, name: str) -> Optional[str]:
279
283
----------
280
284
path : str
281
285
The path where the search starts.
282
- name : str
283
- The file to be found.
286
+ names : List[ str]
287
+ The file to be found (or alternative names) .
284
288
285
289
Returns
286
290
-------
287
291
Optional[str]
288
292
The path where the file has been found or None if no matching file has been found.
289
293
290
294
"""
291
- while True :
292
- p = f"{ path } /{ name } "
293
- if os .path .isfile (p ):
294
- return p
295
- else :
296
- loc = path .rfind ("/" )
297
- if loc == - 1 :
298
- return None
299
- path = path [:loc ]
295
+ start = Path (path ).joinpath (names [0 ]) # the join causes the parents to include path
296
+ for parent in start .parents :
297
+ for name in names :
298
+ file = parent .joinpath (name )
299
+ if file .is_file ():
300
+ if file .name in ["mypy-ls.cfg" , "mypy_ls.cfg" ]:
301
+ raise DeprecationWarning (
302
+ f"{ str (file )} : { file .name } is no longer supported, you should rename your "
303
+ "config file to pylsp-mypy.cfg"
304
+ )
305
+ return str (file )
306
+
307
+ return None
300
308
301
309
302
310
@atexit .register
0 commit comments