1818import tempfile
1919from configparser import ConfigParser
2020from pathlib import Path
21- from typing import IO , Any , Dict , List , Optional
21+ from typing import IO , Any , Optional , TypedDict
2222
2323try :
2424 import tomllib
4747log = logging .getLogger (__name__ )
4848
4949# A mapping from workspace path to config file path
50- mypyConfigFileMap : Dict [str , Optional [str ]] = {}
50+ mypyConfigFileMap : dict [str , Optional [str ]] = {}
5151
52- settingsCache : Dict [str , Dict [str , Any ]] = {}
52+ settingsCache : dict [str , dict [str , Any ]] = {}
5353
5454tmpFile : Optional [IO [bytes ]] = None
5555
5858# so store a cache of last diagnostics for each file a-la the pylint plugin,
5959# so we can return some potentially-stale diagnostics.
6060# 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+
6263
6364# Windows started opening opening a cmd-like window for every subprocess call
6465# This flag prevents that.
6566# 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 {}
6976)
7077
7178
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 ]]:
7380 """
7481 Return a language-server diagnostic from a line of the Mypy error report.
7582
@@ -128,7 +135,7 @@ def parse_line(line: str, document: Optional[Document] = None) -> Optional[Dict[
128135 return diag
129136
130137
131- def apply_overrides (args : List [str ], overrides : List [Any ]) -> List [str ]:
138+ def apply_overrides (args : list [str ], overrides : list [Any ]) -> list [str ]:
132139 """Replace or combine default command-line options with overrides."""
133140 overrides_iterator = iter (overrides )
134141 if True not in overrides_iterator :
@@ -140,7 +147,7 @@ def apply_overrides(args: List[str], overrides: List[Any]) -> List[str]:
140147 return overrides [: - (len (rest ) + 1 )] + args + rest
141148
142149
143- def didSettingsChange (workspace : str , settings : Dict [str , Any ]) -> None :
150+ def didSettingsChange (workspace : str , settings : dict [str , Any ]) -> None :
144151 """Handle relevant changes to the settings between runs."""
145152 configSubPaths = settings .get ("config_sub_paths" , [])
146153 if settingsCache [workspace ].get ("config_sub_paths" , []) != configSubPaths :
@@ -154,7 +161,7 @@ def didSettingsChange(workspace: str, settings: Dict[str, Any]) -> None:
154161 settingsCache [workspace ] = settings .copy ()
155162
156163
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 :
158165 """Check if the current document path matches any of the configures exlude patterns."""
159166 document_path = document_path .replace (os .sep , "/" )
160167
@@ -169,14 +176,14 @@ def match_exclude_patterns(document_path: str, exclude_patterns: list) -> bool:
169176 return False
170177
171178
172- def get_cmd (settings : Dict [str , Any ], cmd : str ) -> List [str ]:
179+ def get_cmd (settings : dict [str , Any ], cmd : str ) -> list [str ]:
173180 """
174181 Get the command to run from settings, falling back to searching the PATH.
175182 If the command is not found in the settings and is not available on the PATH, an
176183 empty list is returned.
177184 """
178185 command_key = f"{ cmd } _command"
179- command : List [str ] = settings .get (command_key , [])
186+ command : list [str ] = settings .get (command_key , [])
180187
181188 if not (command and os .getenv ("PYLSP_MYPY_ALLOW_DANGEROUS_CODE_EXECUTION" )):
182189 # env var is required to allow command from settings
@@ -196,7 +203,7 @@ def get_cmd(settings: Dict[str, Any], cmd: str) -> List[str]:
196203@hookimpl
197204def pylsp_lint (
198205 config : Config , workspace : Workspace , document : Document , is_saved : bool
199- ) -> List [ Dict [str , Any ]]:
206+ ) -> list [ dict [str , Any ]]:
200207 """
201208 Call the linter.
202209
@@ -254,9 +261,9 @@ def pylsp_lint(
254261def get_diagnostics (
255262 workspace : Workspace ,
256263 document : Document ,
257- settings : Dict [str , Any ],
264+ settings : dict [str , Any ],
258265 is_saved : bool ,
259- ) -> List [ Dict [str , Any ]]:
266+ ) -> list [ dict [str , Any ]]:
260267 """
261268 Lints.
262269
@@ -332,7 +339,7 @@ def get_diagnostics(
332339 args .extend (["--incremental" , "--follow-imports" , settings .get ("follow-imports" , "silent" )])
333340 args = apply_overrides (args , overrides )
334341
335- mypy_command : List [str ] = get_cmd (settings , "mypy" )
342+ mypy_command : list [str ] = get_cmd (settings , "mypy" )
336343
337344 if mypy_command :
338345 # mypy exists on PATH or was provided by settings
@@ -357,7 +364,7 @@ def get_diagnostics(
357364 # If daemon is dead/absent, kill will no-op.
358365 # In either case, reset to fresh state
359366
360- dmypy_command : List [str ] = get_cmd (settings , "dmypy" )
367+ dmypy_command : list [str ] = get_cmd (settings , "dmypy" )
361368
362369 if dmypy_command :
363370 # dmypy exists on PATH or was provided by settings
@@ -449,7 +456,7 @@ def get_diagnostics(
449456
450457
451458@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 ]]]:
453460 """
454461 Read the settings.
455462
@@ -468,7 +475,7 @@ def pylsp_settings(config: Config) -> Dict[str, Dict[str, Dict[str, str]]]:
468475 return {"plugins" : {"pylsp_mypy" : configuration }}
469476
470477
471- def init (workspace : str ) -> Dict [str , str ]:
478+ def init (workspace : str ) -> dict [str , str ]:
472479 """
473480 Find plugin and mypy config files and creates the temp file should it be used.
474481
@@ -509,7 +516,7 @@ def init(workspace: str) -> Dict[str, str]:
509516
510517
511518def findConfigFile (
512- path : str , configSubPaths : List [str ], names : List [str ], mypy : bool
519+ path : str , configSubPaths : list [str ], names : list [str ], mypy : bool
513520) -> Optional [str ]:
514521 """
515522 Search for a config file.
@@ -580,9 +587,9 @@ def pylsp_code_actions(
580587 config : Config ,
581588 workspace : Workspace ,
582589 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 ] ]:
586593 """
587594 Provide code actions to ignore errors.
588595
0 commit comments