@@ -143,174 +143,176 @@ def pylsp_lint(
143
143
List of the linting data.
144
144
145
145
"""
146
- settings = config .plugin_settings ("pylsp_mypy" )
147
- oldSettings1 = config .plugin_settings ("mypy-ls" )
148
- if oldSettings1 != {}:
149
- raise DeprecationWarning (
150
- "Your configuration uses the namespace mypy-ls, this should be changed to pylsp_mypy"
151
- )
152
- oldSettings2 = config .plugin_settings ("mypy_ls" )
153
- if oldSettings2 != {}:
154
- raise DeprecationWarning (
155
- "Your configuration uses the namespace mypy_ls, this should be changed to pylsp_mypy"
156
- )
157
- if settings == {}:
158
- settings = oldSettings1
146
+ with workspace .report_progress ("lint: mypy" ):
147
+ settings = config .plugin_settings ("pylsp_mypy" )
148
+ oldSettings1 = config .plugin_settings ("mypy-ls" )
149
+ if oldSettings1 != {}:
150
+ raise DeprecationWarning (
151
+ "Your configuration uses the namespace mypy-ls, this should be changed to pylsp_mypy"
152
+ )
153
+ oldSettings2 = config .plugin_settings ("mypy_ls" )
154
+ if oldSettings2 != {}:
155
+ raise DeprecationWarning (
156
+ "Your configuration uses the namespace mypy_ls, this should be changed to pylsp_mypy"
157
+ )
159
158
if settings == {}:
160
- settings = oldSettings2
161
-
162
- log .info (
163
- "lint settings = %s document.path = %s is_saved = %s" ,
164
- settings ,
165
- document .path ,
166
- is_saved ,
167
- )
168
-
169
- live_mode = settings .get ("live_mode" , True )
170
- dmypy = settings .get ("dmypy" , False )
171
-
172
- if dmypy and live_mode :
173
- # dmypy can only be efficiently run on files that have been saved, see:
174
- # https://github.com/python/mypy/issues/9309
175
- log .warning ("live_mode is not supported with dmypy, disabling" )
176
- live_mode = False
159
+ settings = oldSettings1
160
+ if settings == {}:
161
+ settings = oldSettings2
177
162
178
- args = ["--show-column-numbers" ]
179
-
180
- global tmpFile
181
- if live_mode and not is_saved :
182
- if tmpFile :
183
- tmpFile = open (tmpFile .name , "w" )
184
- else :
185
- tmpFile = tempfile .NamedTemporaryFile ("w" , delete = False )
186
- log .info ("live_mode tmpFile = %s" , tmpFile .name )
187
- tmpFile .write (document .source )
188
- tmpFile .close ()
189
- args .extend (["--shadow-file" , document .path , tmpFile .name ])
190
- elif not is_saved and document .path in last_diagnostics :
191
- # On-launch the document isn't marked as saved, so fall through and run
192
- # the diagnostics anyway even if the file contents may be out of date.
193
163
log .info (
194
- "non-live, returning cached diagnostics len(cached) = %s" ,
195
- last_diagnostics [document .path ],
164
+ "lint settings = %s document.path = %s is_saved = %s" ,
165
+ settings ,
166
+ document .path ,
167
+ is_saved ,
196
168
)
197
- return last_diagnostics [document .path ]
198
169
199
- mypyConfigFile = mypyConfigFileMap .get (workspace .root_path )
200
- if mypyConfigFile :
201
- args .append ("--config-file" )
202
- args .append (mypyConfigFile )
170
+ live_mode = settings .get ("live_mode" , True )
171
+ dmypy = settings .get ("dmypy" , False )
172
+
173
+ if dmypy and live_mode :
174
+ # dmypy can only be efficiently run on files that have been saved, see:
175
+ # https://github.com/python/mypy/issues/9309
176
+ log .warning ("live_mode is not supported with dmypy, disabling" )
177
+ live_mode = False
178
+
179
+ args = ["--show-column-numbers" ]
180
+
181
+ global tmpFile
182
+ if live_mode and not is_saved :
183
+ if tmpFile :
184
+ tmpFile = open (tmpFile .name , "w" )
185
+ else :
186
+ tmpFile = tempfile .NamedTemporaryFile ("w" , delete = False )
187
+ log .info ("live_mode tmpFile = %s" , tmpFile .name )
188
+ tmpFile .write (document .source )
189
+ tmpFile .close ()
190
+ args .extend (["--shadow-file" , document .path , tmpFile .name ])
191
+ elif not is_saved and document .path in last_diagnostics :
192
+ # On-launch the document isn't marked as saved, so fall through and run
193
+ # the diagnostics anyway even if the file contents may be out of date.
194
+ log .info (
195
+ "non-live, returning cached diagnostics len(cached) = %s" ,
196
+ last_diagnostics [document .path ],
197
+ )
198
+ return last_diagnostics [document .path ]
203
199
204
- args .append (document .path )
200
+ mypyConfigFile = mypyConfigFileMap .get (workspace .root_path )
201
+ if mypyConfigFile :
202
+ args .append ("--config-file" )
203
+ args .append (mypyConfigFile )
205
204
206
- if settings .get ("strict" , False ):
207
- args .append ("--strict" )
205
+ args .append (document .path )
208
206
209
- overrides = settings .get ("overrides " , [ True ])
210
- exit_status = 0
207
+ if settings .get ("strict " , False ):
208
+ args . append ( "--strict" )
211
209
212
- if not dmypy :
213
- args .extend (["--incremental" , "--follow-imports" , "silent" ])
214
- args = apply_overrides (args , overrides )
210
+ overrides = settings .get ("overrides" , [True ])
211
+ exit_status = 0
215
212
216
- if shutil .which ("mypy" ):
217
- # mypy exists on path
218
- # -> use mypy on path
219
- log .info ("executing mypy args = %s on path" , args )
220
- completed_process = subprocess .run (
221
- ["mypy" , * args ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , ** windows_flag
222
- )
223
- report = completed_process .stdout .decode ()
224
- errors = completed_process .stderr .decode ()
225
- exit_status = completed_process .returncode
226
- else :
227
- # mypy does not exist on path, but must exist in the env pylsp-mypy is installed in
228
- # -> use mypy via api
229
- log .info ("executing mypy args = %s via api" , args )
230
- report , errors , exit_status = mypy_api .run (args )
231
- else :
232
- # If dmypy daemon is non-responsive calls to run will block.
233
- # Check daemon status, if non-zero daemon is dead or hung.
234
- # If daemon is hung, kill will reset
235
- # If daemon is dead/absent, kill will no-op.
236
- # In either case, reset to fresh state
237
-
238
- if shutil .which ("dmypy" ):
239
- # dmypy exists on path
240
- # -> use mypy on path
241
- completed_process = subprocess .run (
242
- ["dmypy" , "status" ], stderr = subprocess .PIPE , ** windows_flag
243
- )
244
- errors = completed_process .stderr .decode ()
245
- exit_status = completed_process .returncode
246
- if exit_status != 0 :
247
- log .info (
248
- "restarting dmypy from status: %s message: %s via path" ,
249
- exit_status ,
250
- errors .strip (),
213
+ if not dmypy :
214
+ args .extend (["--incremental" , "--follow-imports" , "silent" ])
215
+ args = apply_overrides (args , overrides )
216
+
217
+ if shutil .which ("mypy" ):
218
+ # mypy exists on path
219
+ # -> use mypy on path
220
+ log .info ("executing mypy args = %s on path" , args )
221
+ completed_process = subprocess .run (
222
+ ["mypy" , * args ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , ** windows_flag
251
223
)
252
- subprocess .run (["dmypy" , "restart" ], ** windows_flag )
224
+ report = completed_process .stdout .decode ()
225
+ errors = completed_process .stderr .decode ()
226
+ exit_status = completed_process .returncode
227
+ else :
228
+ # mypy does not exist on path, but must exist in the env pylsp-mypy is installed in
229
+ # -> use mypy via api
230
+ log .info ("executing mypy args = %s via api" , args )
231
+ report , errors , exit_status = mypy_api .run (args )
253
232
else :
254
- # dmypy does not exist on path, but must exist in the env pylsp-mypy is installed in
255
- # -> use dmypy via api
256
- _ , errors , exit_status = mypy_api .run_dmypy (["status" ])
257
- if exit_status != 0 :
258
- log .info (
259
- "restarting dmypy from status: %s message: %s via api" ,
260
- exit_status ,
261
- errors .strip (),
233
+ # If dmypy daemon is non-responsive calls to run will block.
234
+ # Check daemon status, if non-zero daemon is dead or hung.
235
+ # If daemon is hung, kill will reset
236
+ # If daemon is dead/absent, kill will no-op.
237
+ # In either case, reset to fresh state
238
+
239
+ if shutil .which ("dmypy" ):
240
+ # dmypy exists on path
241
+ # -> use mypy on path
242
+ completed_process = subprocess .run (
243
+ ["dmypy" , "status" ], stderr = subprocess .PIPE , ** windows_flag
262
244
)
263
- mypy_api .run_dmypy (["restart" ])
245
+ errors = completed_process .stderr .decode ()
246
+ exit_status = completed_process .returncode
247
+ if exit_status != 0 :
248
+ log .info (
249
+ "restarting dmypy from status: %s message: %s via path" ,
250
+ exit_status ,
251
+ errors .strip (),
252
+ )
253
+ subprocess .run (["dmypy" , "restart" ], ** windows_flag )
254
+ else :
255
+ # dmypy does not exist on path, but must exist in the env pylsp-mypy is installed in
256
+ # -> use dmypy via api
257
+ _ , errors , exit_status = mypy_api .run_dmypy (["status" ])
258
+ if exit_status != 0 :
259
+ log .info (
260
+ "restarting dmypy from status: %s message: %s via api" ,
261
+ exit_status ,
262
+ errors .strip (),
263
+ )
264
+ mypy_api .run_dmypy (["restart" ])
264
265
265
- # run to use existing daemon or restart if required
266
- args = ["run" , "--" ] + apply_overrides (args , overrides )
266
+ # run to use existing daemon or restart if required
267
+ args = ["run" , "--" ] + apply_overrides (args , overrides )
267
268
268
- if shutil .which ("dmypy" ):
269
- # dmypy exists on path
270
- # -> use mypy on path
271
- log .info ("dmypy run args = %s via path" , args )
272
- completed_process = subprocess .run (
273
- ["dmypy" , * args ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , ** windows_flag
269
+ if shutil .which ("dmypy" ):
270
+ # dmypy exists on path
271
+ # -> use mypy on path
272
+ log .info ("dmypy run args = %s via path" , args )
273
+ completed_process = subprocess .run (
274
+ ["dmypy" , * args ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , ** windows_flag
275
+ )
276
+ report = completed_process .stdout .decode ()
277
+ errors = completed_process .stderr .decode ()
278
+ exit_status = completed_process .returncode
279
+ else :
280
+ # dmypy does not exist on path, but must exist in the env pylsp-mypy is installed in
281
+ # -> use dmypy via api
282
+ log .info ("dmypy run args = %s via api" , args )
283
+ report , errors , exit_status = mypy_api .run_dmypy (args )
284
+
285
+ log .debug ("report:\n %s" , report )
286
+ log .debug ("errors:\n %s" , errors )
287
+
288
+ diagnostics = []
289
+
290
+ # Expose generic mypy error on the first line.
291
+ if errors :
292
+ diagnostics .append (
293
+ {
294
+ "source" : "mypy" ,
295
+ "range" : {
296
+ "start" : {"line" : 0 , "character" : 0 },
297
+ # Client is supposed to clip end column to line length.
298
+ "end" : {"line" : 0 , "character" : 1000 },
299
+ },
300
+ "message" : errors ,
301
+ # Error if exited with error or warning.
302
+ "severity" : 1 if exit_status != 0 else 2 ,
303
+ }
274
304
)
275
- report = completed_process .stdout .decode ()
276
- errors = completed_process .stderr .decode ()
277
- exit_status = completed_process .returncode
278
- else :
279
- # dmypy does not exist on path, but must exist in the env pylsp-mypy is installed in
280
- # -> use dmypy via api
281
- log .info ("dmypy run args = %s via api" , args )
282
- report , errors , exit_status = mypy_api .run_dmypy (args )
283
-
284
- log .debug ("report:\n %s" , report )
285
- log .debug ("errors:\n %s" , errors )
286
-
287
- diagnostics = []
288
-
289
- # Expose generic mypy error on the first line.
290
- if errors :
291
- diagnostics .append (
292
- {
293
- "source" : "mypy" ,
294
- "range" : {
295
- "start" : {"line" : 0 , "character" : 0 },
296
- # Client is supposed to clip end column to line length.
297
- "end" : {"line" : 0 , "character" : 1000 },
298
- },
299
- "message" : errors ,
300
- "severity" : 1 if exit_status != 0 else 2 , # Error if exited with error or warning.
301
- }
302
- )
303
305
304
- for line in report .splitlines ():
305
- log .debug ("parsing: line = %r" , line )
306
- diag = parse_line (line , document )
307
- if diag :
308
- diagnostics .append (diag )
306
+ for line in report .splitlines ():
307
+ log .debug ("parsing: line = %r" , line )
308
+ diag = parse_line (line , document )
309
+ if diag :
310
+ diagnostics .append (diag )
309
311
310
- log .info ("pylsp-mypy len(diagnostics) = %s" , len (diagnostics ))
312
+ log .info ("pylsp-mypy len(diagnostics) = %s" , len (diagnostics ))
311
313
312
- last_diagnostics [document .path ] = diagnostics
313
- return diagnostics
314
+ last_diagnostics [document .path ] = diagnostics
315
+ return diagnostics
314
316
315
317
316
318
@hookimpl
0 commit comments