-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Error format support, and JSON output option #11396
Merged
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
393820c
Add -O/--output CLI option
tusharsadhwani 282bd28
Initial formatter setup
tusharsadhwani ccda5b0
Make error_formatter an optional argument
tusharsadhwani c849a77
Fix type annotation
tusharsadhwani fd2feab
Fix whitespace
tusharsadhwani b188001
Remove whitespace
tusharsadhwani 51c1acc
Merge branch 'master' of https://github.com/tusharsadhwani/mypy into …
tusharsadhwani 9177dab
Merge branch 'python:master' into output-json
tushar-deepsource bc5ceac
Add hint property to errors
tushar-deepsource 9d29ab0
Fix lint issues
tusharsadhwani bd6d48d
Merge branch 'master' into output-json
tusharsadhwani ba8d17f
Fix import and typing issues
tusharsadhwani a2bc04d
Fix error tuple signature
tusharsadhwani 35974e4
Import Optional
tusharsadhwani 1e5ec91
Run black
tusharsadhwani 723219f
Run black on another file
tusharsadhwani 2228c0a
Run isort
tusharsadhwani 33d81b0
Run isort on build.py
tusharsadhwani 63001ea
Merge branch 'master' into output-json
tusharsadhwani d27be7e
Merge branch 'master' into output-json
tusharsadhwani efe5c5d
Merge branch 'master' into output-json
tusharsadhwani 1872ae6
Add tests for json output
tusharsadhwani 3abc9cb
Suggestions from code review, and negative test
tusharsadhwani 6c9ab11
Add default value of None
tusharsadhwani 627ed8e
Default output to None in options as well
tusharsadhwani e425cbe
Fix failing tests
tusharsadhwani 47f1b07
improve docstring
tusharsadhwani e00ad4a
type cast
tusharsadhwani c1fb6a2
Another explicit type cast
tusharsadhwani aafe3aa
remove unused import
tusharsadhwani fae3215
create formatter object
tusharsadhwani 89ad1d3
Add custom end to end test
tusharsadhwani 7a3f736
unused import
tusharsadhwani 6d46f75
trailing whitespace
tusharsadhwani e71a372
try fixing windows
tusharsadhwani 8cca203
fix windows separator issue
tusharsadhwani 79e16a8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 8bf4890
unused import
tusharsadhwani 5899f26
Merge branch 'master' into output-json
tusharsadhwani 880b8f3
Merge branch 'master' into output-json
tusharsadhwani 0aafadf
Pass error tuples to format_messages
tusharsadhwani 4cab249
Merge branch 'master' into output-json
tusharsadhwani 7fe71c3
Merge branch 'master' into output-json
tusharsadhwani ad8f1d6
Merge branch 'master' into output-json
tusharsadhwani e2fd45e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 4b03c5c
ruff lints
tusharsadhwani e0e6896
address comments
tusharsadhwani a0dc6d1
use severity
tusharsadhwani File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
"""Defines the different custom formats in which mypy can output.""" | ||
|
||
import json | ||
from abc import ABC, abstractmethod | ||
from typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: | ||
from mypy.errors import MypyError | ||
|
||
|
||
class ErrorFormatter(ABC): | ||
"""Base class to define how errors are formatted before being printed.""" | ||
|
||
@abstractmethod | ||
def report_error(self, error: "MypyError") -> str: | ||
raise NotImplementedError | ||
|
||
|
||
class JSONFormatter(ErrorFormatter): | ||
"""Formatter for basic JSON output format.""" | ||
|
||
def report_error(self, error: "MypyError") -> str: | ||
"""Prints out the errors as simple, static JSON lines.""" | ||
return json.dumps( | ||
{ | ||
"file": error.file_path, | ||
"line": error.line, | ||
"column": error.column, | ||
"message": error.message, | ||
"hint": None if len(error.hints) == 0 else "\n".join(error.hints), | ||
"code": None if error.errorcode is None else error.errorcode.code, | ||
"severity": error.severity, | ||
} | ||
) | ||
|
||
|
||
OUTPUT_CHOICES = {"json": JSONFormatter()} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
"""Test cases for `--output=json`. | ||
|
||
These cannot be run by the usual unit test runner because of the backslashes in | ||
the output, which get normalized to forward slashes by the test suite on Windows. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
import os | ||
import os.path | ||
|
||
from mypy import api | ||
from mypy.defaults import PYTHON3_VERSION | ||
from mypy.test.config import test_temp_dir | ||
from mypy.test.data import DataDrivenTestCase, DataSuite | ||
|
||
|
||
class OutputJSONsuite(DataSuite): | ||
files = ["outputjson.test"] | ||
|
||
def run_case(self, testcase: DataDrivenTestCase) -> None: | ||
test_output_json(testcase) | ||
|
||
|
||
def test_output_json(testcase: DataDrivenTestCase) -> None: | ||
"""Runs Mypy in a subprocess, and ensures that `--output=json` works as intended.""" | ||
mypy_cmdline = ["--output=json"] | ||
mypy_cmdline.append(f"--python-version={'.'.join(map(str, PYTHON3_VERSION))}") | ||
|
||
# Write the program to a file. | ||
program_path = os.path.join(test_temp_dir, "main") | ||
mypy_cmdline.append(program_path) | ||
with open(program_path, "w", encoding="utf8") as file: | ||
for s in testcase.input: | ||
file.write(f"{s}\n") | ||
|
||
output = [] | ||
# Type check the program. | ||
out, err, returncode = api.run(mypy_cmdline) | ||
# split lines, remove newlines, and remove directory of test case | ||
for line in (out + err).rstrip("\n").splitlines(): | ||
if line.startswith(test_temp_dir + os.sep): | ||
output.append(line[len(test_temp_dir + os.sep) :].rstrip("\r\n")) | ||
else: | ||
output.append(line.rstrip("\r\n")) | ||
|
||
if returncode > 1: | ||
output.append("!!! Mypy crashed !!!") | ||
|
||
# Remove temp file. | ||
os.remove(program_path) | ||
|
||
# JSON encodes every `\` character into `\\`, so we need to remove `\\` from windows paths | ||
# and `/` from POSIX paths | ||
json_os_separator = os.sep.replace("\\", "\\\\") | ||
normalized_output = [line.replace(test_temp_dir + json_os_separator, "") for line in output] | ||
|
||
assert normalized_output == testcase.output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
-- Test cases for `--output=json`. | ||
-- These cannot be run by the usual unit test runner because of the backslashes | ||
-- in the output, which get normalized to forward slashes by the test suite on | ||
-- Windows. | ||
|
||
[case testOutputJsonNoIssues] | ||
# flags: --output=json | ||
def foo() -> None: | ||
pass | ||
|
||
foo() | ||
[out] | ||
|
||
[case testOutputJsonSimple] | ||
# flags: --output=json | ||
def foo() -> None: | ||
pass | ||
|
||
foo(1) | ||
[out] | ||
{"file": "main", "line": 5, "column": 0, "message": "Too many arguments for \"foo\"", "hint": null, "code": "call-arg", "severity": "error"} | ||
|
||
[case testOutputJsonWithHint] | ||
# flags: --output=json | ||
from typing import Optional, overload | ||
|
||
@overload | ||
def foo() -> None: ... | ||
@overload | ||
def foo(x: int) -> None: ... | ||
|
||
def foo(x: Optional[int] = None) -> None: | ||
... | ||
|
||
reveal_type(foo) | ||
|
||
foo('42') | ||
|
||
def bar() -> None: ... | ||
bar('42') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a test case with |
||
[out] | ||
{"file": "main", "line": 12, "column": 12, "message": "Revealed type is \"Overload(def (), def (x: builtins.int))\"", "hint": null, "code": "misc", "severity": "note"} | ||
{"file": "main", "line": 14, "column": 0, "message": "No overload variant of \"foo\" matches argument type \"str\"", "hint": "Possible overload variants:\n def foo() -> None\n def foo(x: int) -> None", "code": "call-overload", "severity": "error"} | ||
{"file": "main", "line": 17, "column": 0, "message": "Too many arguments for \"bar\"", "hint": null, "code": "call-arg", "severity": "error"} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This module should define a dictionary
str -> ErrorFormatter
that can be used inbuild.py
.