18
18
import tempfile
19
19
from configparser import ConfigParser
20
20
from pathlib import Path
21
- from typing import IO , Any , Dict , List , Optional
21
+ from typing import IO , Any , Optional , TypedDict
22
22
23
23
try :
24
24
import tomllib
47
47
log = logging .getLogger (__name__ )
48
48
49
49
# A mapping from workspace path to config file path
50
- mypyConfigFileMap : Dict [str , Optional [str ]] = {}
50
+ mypyConfigFileMap : dict [str , Optional [str ]] = {}
51
51
52
- settingsCache : Dict [str , Dict [str , Any ]] = {}
52
+ settingsCache : dict [str , dict [str , Any ]] = {}
53
53
54
54
tmpFile : Optional [IO [bytes ]] = None
55
55
58
58
# so store a cache of last diagnostics for each file a-la the pylint plugin,
59
59
# so we can return some potentially-stale diagnostics.
60
60
# https://github.com/python-lsp/python-lsp-server/blob/v1.0.1/pylsp/plugins/pylint_lint.py#L55-L62
61
- last_diagnostics : Dict [str , List [Dict [str , Any ]]] = collections .defaultdict (list )
61
+ last_diagnostics : dict [str , list [dict [str , Any ]]] = collections .defaultdict (list )
62
+
62
63
63
64
# Windows started opening opening a cmd-like window for every subprocess call
64
65
# This flag prevents that.
65
66
# This flag is new in python 3.7
66
- # This flag only exists on Windows
67
- windows_flag : Dict [str , int ] = (
68
- {"creationflags" : subprocess .CREATE_NO_WINDOW } if os .name == "nt" else {} # type: ignore
67
+ # This flag only exists on Windows, hence the 'type: ignore[attr-defined]' below.
68
+ class WindowsFlag (TypedDict , total = False ):
69
+ creationflags : int
70
+
71
+
72
+ windows_flag : WindowsFlag = (
73
+ {"creationflags" : subprocess .CREATE_NO_WINDOW } # type: ignore[attr-defined]
74
+ if os .name == "nt"
75
+ else {}
69
76
)
70
77
71
78
72
- def parse_line (line : str , document : Optional [Document ] = None ) -> Optional [Dict [str , Any ]]:
79
+ def parse_line (line : str , document : Optional [Document ] = None ) -> Optional [dict [str , Any ]]:
73
80
"""
74
81
Return a language-server diagnostic from a line of the Mypy error report.
75
82
@@ -128,7 +135,7 @@ def parse_line(line: str, document: Optional[Document] = None) -> Optional[Dict[
128
135
return diag
129
136
130
137
131
- def apply_overrides (args : List [str ], overrides : List [Any ]) -> List [str ]:
138
+ def apply_overrides (args : list [str ], overrides : list [Any ]) -> list [str ]:
132
139
"""Replace or combine default command-line options with overrides."""
133
140
overrides_iterator = iter (overrides )
134
141
if True not in overrides_iterator :
@@ -140,7 +147,7 @@ def apply_overrides(args: List[str], overrides: List[Any]) -> List[str]:
140
147
return overrides [: - (len (rest ) + 1 )] + args + rest
141
148
142
149
143
- def didSettingsChange (workspace : str , settings : Dict [str , Any ]) -> None :
150
+ def didSettingsChange (workspace : str , settings : dict [str , Any ]) -> None :
144
151
"""Handle relevant changes to the settings between runs."""
145
152
configSubPaths = settings .get ("config_sub_paths" , [])
146
153
if settingsCache [workspace ].get ("config_sub_paths" , []) != configSubPaths :
@@ -154,7 +161,7 @@ def didSettingsChange(workspace: str, settings: Dict[str, Any]) -> None:
154
161
settingsCache [workspace ] = settings .copy ()
155
162
156
163
157
- def match_exclude_patterns (document_path : str , exclude_patterns : list ) -> bool :
164
+ def match_exclude_patterns (document_path : str , exclude_patterns : list [ str ] ) -> bool :
158
165
"""Check if the current document path matches any of the configures exlude patterns."""
159
166
document_path = document_path .replace (os .sep , "/" )
160
167
@@ -169,14 +176,14 @@ def match_exclude_patterns(document_path: str, exclude_patterns: list) -> bool:
169
176
return False
170
177
171
178
172
- def get_cmd (settings : Dict [str , Any ], cmd : str ) -> List [str ]:
179
+ def get_cmd (settings : dict [str , Any ], cmd : str ) -> list [str ]:
173
180
"""
174
181
Get the command to run from settings, falling back to searching the PATH.
175
182
If the command is not found in the settings and is not available on the PATH, an
176
183
empty list is returned.
177
184
"""
178
185
command_key = f"{ cmd } _command"
179
- command : List [str ] = settings .get (command_key , [])
186
+ command : list [str ] = settings .get (command_key , [])
180
187
181
188
if not (command and os .getenv ("PYLSP_MYPY_ALLOW_DANGEROUS_CODE_EXECUTION" )):
182
189
# env var is required to allow command from settings
@@ -196,7 +203,7 @@ def get_cmd(settings: Dict[str, Any], cmd: str) -> List[str]:
196
203
@hookimpl
197
204
def pylsp_lint (
198
205
config : Config , workspace : Workspace , document : Document , is_saved : bool
199
- ) -> List [ Dict [str , Any ]]:
206
+ ) -> list [ dict [str , Any ]]:
200
207
"""
201
208
Call the linter.
202
209
@@ -254,9 +261,9 @@ def pylsp_lint(
254
261
def get_diagnostics (
255
262
workspace : Workspace ,
256
263
document : Document ,
257
- settings : Dict [str , Any ],
264
+ settings : dict [str , Any ],
258
265
is_saved : bool ,
259
- ) -> List [ Dict [str , Any ]]:
266
+ ) -> list [ dict [str , Any ]]:
260
267
"""
261
268
Lints.
262
269
@@ -332,7 +339,7 @@ def get_diagnostics(
332
339
args .extend (["--incremental" , "--follow-imports" , settings .get ("follow-imports" , "silent" )])
333
340
args = apply_overrides (args , overrides )
334
341
335
- mypy_command : List [str ] = get_cmd (settings , "mypy" )
342
+ mypy_command : list [str ] = get_cmd (settings , "mypy" )
336
343
337
344
if mypy_command :
338
345
# mypy exists on PATH or was provided by settings
@@ -357,7 +364,7 @@ def get_diagnostics(
357
364
# If daemon is dead/absent, kill will no-op.
358
365
# In either case, reset to fresh state
359
366
360
- dmypy_command : List [str ] = get_cmd (settings , "dmypy" )
367
+ dmypy_command : list [str ] = get_cmd (settings , "dmypy" )
361
368
362
369
if dmypy_command :
363
370
# dmypy exists on PATH or was provided by settings
@@ -449,7 +456,7 @@ def get_diagnostics(
449
456
450
457
451
458
@hookimpl
452
- def pylsp_settings (config : Config ) -> Dict [str , Dict [str , Dict [str , str ]]]:
459
+ def pylsp_settings (config : Config ) -> dict [str , dict [str , dict [str , str ]]]:
453
460
"""
454
461
Read the settings.
455
462
@@ -468,7 +475,7 @@ def pylsp_settings(config: Config) -> Dict[str, Dict[str, Dict[str, str]]]:
468
475
return {"plugins" : {"pylsp_mypy" : configuration }}
469
476
470
477
471
- def init (workspace : str ) -> Dict [str , str ]:
478
+ def init (workspace : str ) -> dict [str , str ]:
472
479
"""
473
480
Find plugin and mypy config files and creates the temp file should it be used.
474
481
@@ -509,7 +516,7 @@ def init(workspace: str) -> Dict[str, str]:
509
516
510
517
511
518
def findConfigFile (
512
- path : str , configSubPaths : List [str ], names : List [str ], mypy : bool
519
+ path : str , configSubPaths : list [str ], names : list [str ], mypy : bool
513
520
) -> Optional [str ]:
514
521
"""
515
522
Search for a config file.
@@ -580,9 +587,9 @@ def pylsp_code_actions(
580
587
config : Config ,
581
588
workspace : Workspace ,
582
589
document : Document ,
583
- range : Dict ,
584
- context : Dict ,
585
- ) -> List [ Dict ]:
590
+ range : dict [ str , Any ] ,
591
+ context : dict [ str , Any ] ,
592
+ ) -> list [ dict [ str , Any ] ]:
586
593
"""
587
594
Provide code actions to ignore errors.
588
595
0 commit comments