|
1 | 1 | import collections
|
2 | 2 | import os
|
| 3 | +import re |
3 | 4 | import subprocess
|
4 | 5 | import sys
|
5 | 6 | from pathlib import Path
|
6 | 7 | from typing import Dict
|
7 |
| -from unittest.mock import Mock |
| 8 | +from unittest.mock import Mock, patch |
8 | 9 |
|
9 | 10 | import pytest
|
10 | 11 | from mypy import api as mypy_api
|
|
18 | 19 | DOC_URI = f"file:/{Path(__file__)}"
|
19 | 20 | DOC_TYPE_ERR = """{}.append(3)
|
20 | 21 | """
|
21 |
| -TYPE_ERR_MSG = '"Dict[<nothing>, <nothing>]" has no attribute "append"' |
| 22 | + |
| 23 | +# Mypy 1.7 changed <nothing> into "Never", so make this a regex to be compatible |
| 24 | +# with multiple versions of mypy |
| 25 | +TYPE_ERR_MSG_REGEX = ( |
| 26 | + r'"Dict\[(?:(?:<nothing>)|(?:Never)), (?:(?:<nothing>)|(?:Never))\]" has no attribute "append"' |
| 27 | +) |
22 | 28 |
|
23 | 29 | TEST_LINE = 'test_plugin.py:279:8:279:16: error: "Request" has no attribute "id" [attr-defined]'
|
24 | 30 | TEST_LINE_NOTE = (
|
@@ -66,7 +72,7 @@ def test_plugin(workspace, last_diagnostics_monkeypatch):
|
66 | 72 |
|
67 | 73 | assert len(diags) == 1
|
68 | 74 | diag = diags[0]
|
69 |
| - assert diag["message"] == TYPE_ERR_MSG |
| 75 | + assert re.fullmatch(TYPE_ERR_MSG_REGEX, diag["message"]) |
70 | 76 | assert diag["range"]["start"] == {"line": 0, "character": 0}
|
71 | 77 | # Running mypy in 3.7 produces wrong error ends this can be removed when 3.7 reaches EOL
|
72 | 78 | if sys.version_info < (3, 8):
|
@@ -328,3 +334,47 @@ def foo():
|
328 | 334 | diag = diags[0]
|
329 | 335 | assert diag["message"] == DOC_ERR_MSG
|
330 | 336 | assert diag["code"] == "unreachable"
|
| 337 | + |
| 338 | + |
| 339 | +@pytest.mark.parametrize( |
| 340 | + "document_path,pattern,os_sep,pattern_matched", |
| 341 | + ( |
| 342 | + ("/workspace/my-file.py", "/someting-else", "/", False), |
| 343 | + ("/workspace/my-file.py", "^/workspace$", "/", False), |
| 344 | + ("/workspace/my-file.py", "/workspace", "/", True), |
| 345 | + ("/workspace/my-file.py", "^/workspace(.*)$", "/", True), |
| 346 | + # This is a broken regex (missing ')'), but should not choke |
| 347 | + ("/workspace/my-file.py", "/((workspace)", "/", False), |
| 348 | + # Windows paths are tricky with all those \\ and unintended escape, |
| 349 | + # characters but they should 'just' work |
| 350 | + ("d:\\a\\my-file.py", "/a", "\\", True), |
| 351 | + ( |
| 352 | + "d:\\a\\pylsp-mypy\\pylsp-mypy\\test\\test_plugin.py", |
| 353 | + "/a/pylsp-mypy/pylsp-mypy/test/test_plugin.py", |
| 354 | + "\\", |
| 355 | + True, |
| 356 | + ), |
| 357 | + ), |
| 358 | +) |
| 359 | +def test_match_exclude_patterns(document_path, pattern, os_sep, pattern_matched): |
| 360 | + with patch("os.sep", new=os_sep): |
| 361 | + assert ( |
| 362 | + plugin.match_exclude_patterns(document_path=document_path, exclude_patterns=[pattern]) |
| 363 | + is pattern_matched |
| 364 | + ) |
| 365 | + |
| 366 | + |
| 367 | +def test_config_exclude(tmpdir, workspace): |
| 368 | + """When exclude is set in config then mypy should not run for that file.""" |
| 369 | + doc = Document(DOC_URI, workspace, DOC_TYPE_ERR) |
| 370 | + |
| 371 | + plugin.pylsp_settings(workspace._config) |
| 372 | + workspace.update_config({"pylsp": {"plugins": {"pylsp_mypy": {}}}}) |
| 373 | + diags = plugin.pylsp_lint(workspace._config, workspace, doc, is_saved=False) |
| 374 | + assert re.search(TYPE_ERR_MSG_REGEX, diags[0]["message"]) |
| 375 | + |
| 376 | + # Add the path of our document to the exclude patterns |
| 377 | + exclude_path = doc.path.replace(os.sep, "/") |
| 378 | + workspace.update_config({"pylsp": {"plugins": {"pylsp_mypy": {"exclude": [exclude_path]}}}}) |
| 379 | + diags = plugin.pylsp_lint(workspace._config, workspace, doc, is_saved=False) |
| 380 | + assert diags == [] |
0 commit comments