Skip to content

Commit

Permalink
Encode patterns so patterns like "d:\\a\..." do work
Browse files Browse the repository at this point in the history
Especially useful when using Windows paths
  • Loading branch information
maerteijn committed Oct 21, 2023
1 parent 5888f74 commit 22d4b72
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 8 deletions.
31 changes: 24 additions & 7 deletions pylsp_mypy/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,23 @@ def didSettingsChange(workspace: str, settings: Dict[str, Any]) -> None:
settingsCache[workspace] = settings.copy()


def match_exclude_patterns(document_path: str, exclude_patterns: list) -> bool:
for pattern in exclude_patterns:
# This makes sure that \\ characters (and other unicode characters) are
# escaped first so the regex matcher will be able to parse them correctly.
# Especially useful for matching windows paths without any bad escape errors
pattern = pattern.encode("unicode-escape").decode()

try:
if re.search(pattern, document_path):
log.debug(f"{document_path} matches " f"exclude pattern '{pattern}'")
return True
except re.error as e:
log.error(f"pattern {pattern} is not a valid regular expression: {e}")

return False


@hookimpl
def pylsp_lint(
config: Config, workspace: Workspace, document: Document, is_saved: bool
Expand Down Expand Up @@ -185,13 +202,13 @@ def pylsp_lint(
# configured with mypy. We can now add our own exclude section like so:
# [tool.pylsp-mypy]
# exclude = ["tests/*"]
exclude = settings.get("exclude", [])
for pattern in exclude:
if re.search(pattern, document.path):
log.debug(
f"Not running because {document.path} matches " f"exclude pattern '{pattern}'"
)
return []
exclude_patterns = settings.get("exclude", [])

if match_exclude_patterns(document_path=document.path, exclude_patterns=exclude_patterns):
log.debug(
f"Not running because {document.path} matches " f"exclude patterns '{exclude_patterns}'"
)
return []

if settings.get("report_progress", False):
with workspace.report_progress("lint: mypy"):
Expand Down
28 changes: 27 additions & 1 deletion test/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,33 @@ def foo():
assert diag["code"] == "unreachable"


def test_exclude_path_match_mypy_not_run(tmpdir, workspace):
@pytest.mark.parametrize(
"document_path,pattern,pattern_matched",
(
("/workspace/my-file.py", "/someting-else", False),
("/workspace/my-file.py", "^/workspace$", False),
("/workspace/my-file.py", "/workspace", True),
("/workspace/my-file.py", "^/workspace(.*)$", True),
# This is a broken regex (missing ')'), but should not choke
("/workspace/my-file.py", "/((workspace)", False),
# Windows paths are tricky with all those \\ and unintended escape,
# characters but they should 'just' work
("d:\\a\\my-file.py", "\\a", True),
(
"d:\\a\\pylsp-mypy\\pylsp-mypy\\test\\test_plugin.py",
"d:\\a\\pylsp-mypy\\pylsp-mypy\\test\\test_plugin.py",
True,
),
),
)
def test_match_exclude_patterns(document_path, pattern, pattern_matched):
assert (
plugin.match_exclude_patterns(document_path=document_path, exclude_patterns=[pattern])
is pattern_matched
)


def test_config_exclude(tmpdir, workspace):
"""When exclude is set in config then mypy should not run for that file."""
doc = Document(DOC_URI, workspace, DOC_TYPE_ERR)

Expand Down

0 comments on commit 22d4b72

Please sign in to comment.