diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d689c335..babb0002 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: pyproject.toml| )$ - repo: https://github.com/PyCQA/prospector - rev: v1.10.3 + rev: v1.13.3 hooks: - id: prospector additional_dependencies: diff --git a/prospector/formatters/base.py b/prospector/formatters/base.py index f2d3db03..6c42ded9 100644 --- a/prospector/formatters/base.py +++ b/prospector/formatters/base.py @@ -39,9 +39,18 @@ def _message_to_dict(self, message: Message) -> dict[str, Any]: "line": message.location.line, "character": message.location.character, } - return { + if message.location.line_end is not None and message.location.line_end != -1: + loc["lineEnd"] = message.location.line_end + if message.location.character_end is not None and message.location.character_end != -1: + loc["characterEnd"] = message.location.character_end + result = { "source": message.source, "code": message.code, "location": loc, "message": message.message, + "isFixable": message.is_fixable, } + if message.doc_url: + result["docUrl"] = message.doc_url + + return message diff --git a/prospector/formatters/pylint.py b/prospector/formatters/pylint.py index 957d27d5..6f29332e 100644 --- a/prospector/formatters/pylint.py +++ b/prospector/formatters/pylint.py @@ -49,6 +49,9 @@ def render_messages(self) -> list[str]: else f"{template_code}: %(message)s" ) + message_str = message.message.strip() + if message.doc_url: + message_str += f" (See: {message.doc_url})" output.append( template % { diff --git a/prospector/message.py b/prospector/message.py index 34f5942e..6f3b08b7 100644 --- a/prospector/message.py +++ b/prospector/message.py @@ -12,6 +12,8 @@ def __init__( function: Optional[str], line: Optional[int], character: Optional[int], + line_end: Optional[int] = None, + character_end: Optional[int] = None, ): if isinstance(path, Path): self._path = path.absolute() @@ -25,6 +27,8 @@ def __init__( self.function = function or None self.line = None if line == -1 else line self.character = None if character == -1 else character + self.line_end = line_end + self.character_end = character_end @property def path(self) -> Optional[Path]: @@ -69,11 +73,21 @@ def __lt__(self, other: "Location") -> bool: class Message: - def __init__(self, source: str, code: str, location: Location, message: str): + def __init__( + self, + source: str, + code: str, + location: Location, + message: str, + doc_url: Optional[str] = None, + is_fixable: bool = False, + ): self.source = source self.code = code self.location = location self.message = message + self.doc_url = doc_url + self.is_fixable = is_fixable def __repr__(self) -> str: return f"{self.source}-{self.code}" diff --git a/prospector/tools/bandit/__init__.py b/prospector/tools/bandit/__init__.py index d302cc90..b5a53c24 100644 --- a/prospector/tools/bandit/__init__.py +++ b/prospector/tools/bandit/__init__.py @@ -66,7 +66,15 @@ def run(self, found_files: FileFinder) -> list[Message]: results = self.manager.get_issue_list(sev_level=RANKING[self.severity], conf_level=RANKING[self.confidence]) messages = [] for result in results: - loc = Location(result.fname, None, "", int(result.lineno), 0) + loc = Location( + result.fname, + None, + "", + result.lineno, + result.col_offset, + line_end=result.linerange[-1] if result.linerange else result.lineno, + character_end=result.end_col_offset, + ) msg = Message("bandit", result.test_id, loc, result.text) messages.append(msg) return messages diff --git a/prospector/tools/mypy/__init__.py b/prospector/tools/mypy/__init__.py index a897383b..45275e45 100644 --- a/prospector/tools/mypy/__init__.py +++ b/prospector/tools/mypy/__init__.py @@ -87,7 +87,7 @@ def configure(self, prospector_config: "ProspectorConfig", _: Any) -> None: self.options.append(f"--{name}-{v}") continue - raise BadToolConfig("mypy", f"The option {name} has an unsupported balue type: {type(value)}") + raise BadToolConfig("mypy", f"The option {name} has an unsupported value type: {type(value)}") def run(self, found_files: FileFinder) -> list[Message]: paths = [str(path) for path in found_files.python_modules] diff --git a/prospector/tools/pylint/collector.py b/prospector/tools/pylint/collector.py index 1002bc10..3cb942cb 100644 --- a/prospector/tools/pylint/collector.py +++ b/prospector/tools/pylint/collector.py @@ -17,7 +17,7 @@ def __init__(self, message_store: MessageDefinitionStore) -> None: self._messages: list[Message] = [] def handle_message(self, msg: PylintMessage) -> None: - loc = Location(msg.abspath, msg.module, msg.obj, msg.line, msg.column) + loc = Location(msg.abspath, msg.module, msg.obj, msg.line, msg.column, msg.end_line, msg.end_column) # At this point pylint will give us the code but we want the # more user-friendly symbol diff --git a/prospector/tools/ruff/__init__.py b/prospector/tools/ruff/__init__.py index 6aca01ba..f6e9c4fc 100644 --- a/prospector/tools/ruff/__init__.py +++ b/prospector/tools/ruff/__init__.py @@ -59,8 +59,6 @@ def run(self, found_files: FileFinder) -> list[Message]: return messages for message in json.loads(completed_process.stdout): sub_message = {} - if message.get("url"): - sub_message["See"] = message["url"] if message.get("fix") and message["fix"].get("applicability"): sub_message["Fix applicability"] = message["fix"]["applicability"] message_str = message.get("message", "") @@ -77,8 +75,12 @@ def run(self, found_files: FileFinder) -> list[Message]: None, line=message.get("location", {}).get("row"), character=message.get("location", {}).get("column"), + line_end=message.get("end_location", {}).get("row"), + character_end=message.get("end_location", {}).get("column"), ), message_str, + doc_url=message.get("url"), + is_fixable=bool((message.get("fix") or {}).get("applicability") in ("safe", "unsafe")), ) ) return messages