Source code for project_config.reporters.json_

"""JSON reporters."""

from __future__ import annotations

import json
from typing import Any

from project_config.reporters.base import BaseColorReporter, BaseReporter


[docs]class JsonReporter(BaseReporter): """Black/white reporter in JSON format."""
[docs] def generate_errors_report(self) -> str: """Generate an errors report in black/white JSON format.""" return json.dumps( self.errors, indent=( 2 if self.format == "pretty" else (4 if self.format == "pretty4" else None) ), )
[docs] def generate_data_report( self, _data_key: str, data: dict[str, Any], ) -> str: """Generate a data report in black/white JSON format.""" return json.dumps( data, indent=( 2 if self.format == "pretty" else (4 if self.format == "pretty4" else None) ), )
[docs]class JsonColorReporter(BaseColorReporter): """Color reporter in JSON format."""
[docs] def generate_errors_report(self) -> str: # noqa: PLR0912 """Generate an errors report in JSON format with colors.""" message_key = self.format_key('"message"') definition_key = self.format_key('"definition"') hint_key = self.format_key('"hint"') fixed_key = self.format_key('"fixed"') fixable_key = self.format_key('"fixable"') space = " " if not self.format: # separators for pretty formatting newline0 = newline2 = newline4 = newline6 = "" else: mul = 1 if self.format == "pretty" else 2 newline0 = "\n" newline2 = "\n" + space * 2 * mul newline4 = "\n" + space * 4 * mul newline6 = "\n" + space * 6 * mul if not self.errors: return "{}" report = f"{self.format_metachar('{')}{newline2}" for f, (file, errors) in enumerate(self.errors.items()): report += ( self.format_file(json.dumps(file)) + self.format_metachar(": [") + newline4 ) for e, error in enumerate(errors): error_message = self.format_error_message( json.dumps(error["message"]), ) definition = self.format_definition( json.dumps(error["definition"]), ) report += ( f"{self.format_metachar('{')}{newline6}{message_key}:" f" {error_message}" f'{self.format_metachar(",")}{newline6 or space}' f'{definition_key}{self.format_metachar(":")}' f" {definition}" ) if "hint" in error: hint = self.format_hint(json.dumps(error["hint"])) report += ( f'{self.format_metachar(",")}{newline6 or space}' f'{hint_key}{self.format_metachar(":")}' f" {hint}" ) try: if error.pop("fixable"): if error.pop("fixed"): report += ( f'{self.format_metachar(",")}' f"{newline6 or space}" f'{fixed_key}{self.format_metachar(":")}' f" {self.format_fixed('true')}" ) else: report += ( f'{self.format_metachar(",")}' f"{newline6 or space}" f'{fixable_key}{self.format_metachar(":")}' f" {self.format_fixed('true')}" ) except KeyError: pass report += f"{newline4}{self.format_metachar('}')}" if e < len(errors) - 1: report += f'{self.format_metachar(",")}{newline4 or space}' report += f"{newline2}{self.format_metachar(']')}" if f < len(self.errors) - 1: report += f'{self.format_metachar(",")}{newline2 or space}' return f"{report}{newline0}{self.format_metachar('}')}"
[docs] def generate_data_report( # noqa: PLR0912, PLR0915 self, data_key: str, data: dict[str, Any], ) -> str: """Generate data report in JSON format with colors.""" space = " " if not self.format: newline0 = newline2 = newline4 = newline6 = newline8 = "" newline10 = newline12 = "" else: mul = 1 if self.format == "pretty" else 2 newline0 = "\n" newline2 = "\n" + space * 2 * mul newline4 = "\n" + space * 4 * mul newline6 = "\n" + space * 6 * mul newline8 = "\n" + space * 8 * mul newline10 = "\n" + space * 10 * mul newline12 = "\n" + space * 10 * mul report = f"{self.format_metachar('{')}{newline2}" if data_key == "style": plugins = data.pop("plugins", []) if plugins: report += ( f'{self.format_config_key(json.dumps("plugins"))}' f'{self.format_metachar(":")}' f'{space}{self.format_metachar("[")}{newline4}' ) for p, plugin in enumerate(plugins): report += f"{self.format_config_value(json.dumps(plugin))}" if p < len(plugins) - 1: report += ( f'{self.format_metachar(",")}{newline4 or space}' ) report += ( f'{newline2}{self.format_metachar("],")}{newline2 or space}' ) report += ( f'{self.format_config_key(json.dumps("rules"))}' f'{self.format_metachar(":")}' f'{space}{self.format_metachar("[")}{newline4}' ) rules = data.pop("rules") for r, rule in enumerate(rules): report += ( f'{self.format_metachar("{")}{newline6}' f'{self.format_key(json.dumps("files"))}' f'{self.format_metachar(":")}{space}' ) files = rule.pop("files") if "not" in files and len(files) == 1: report += ( f"{self.format_metachar('{')}{newline8}" f"{self.format_key(json.dumps('not'))}" f"{self.format_metachar(':')}{space}" ) if isinstance(files["not"], list): # [...files...] report += f'{self.format_metachar("[")}{newline10}' for f, file in enumerate(files["not"]): report += f"{self.format_file(json.dumps(file))}" if f < len(files["not"]) - 1: report += ( f'{self.format_metachar(",")}' f"{newline10 or space}" ) else: report += ( f'{newline8}{self.format_metachar("]")}' ) report += f'{newline6}{self.format_metachar("}")}' else: report += f'{self.format_metachar("{")}{newline12}' for f, (file, reason) in enumerate( files["not"].items(), ): formatted_reason = self.format_config_value( json.dumps(reason), ) report += ( f"{self.format_file(json.dumps(file))}" f'{self.format_metachar(":")}' f"{space}{formatted_reason}" ) if f < len(files["not"]) - 1: report += ( f'{self.format_metachar(",")}' f"{newline10 or space}" ) else: report += newline8 report += ( f'{self.format_metachar("}")}{newline6}' f'{self.format_metachar("}")}' ) else: report += f"{self.format_metachar('[')}{newline8}" for f, file in enumerate(files): report += f"{self.format_file(json.dumps(file))}" if f < len(files) - 1: report += ( f'{self.format_metachar(",")}' f"{newline8 or space}" ) else: report += f'{newline6}{self.format_metachar("]")}' for action_index, (action_name, action_value) in enumerate( rule.items(), ): if action_index == 0: report += ( f'{self.format_metachar(",")}{newline6 or space}' ) indented_value = "\n".join( ((space * 6 * mul + line) if line_index > 0 else line) for line_index, line in enumerate( json.dumps( action_value, indent=( None if not self.format else (4 if "4" in self.format else 2) ), ).splitlines(), ) ) report += ( f"{self.format_key(json.dumps(action_name))}" f'{self.format_metachar(":")}' f"{space}" f"{self.format_config_value(indented_value)}" ) if action_index < len(rule) - 1: report += ( f'{self.format_metachar(",")}{newline6 or space}' ) report += f'{newline4}{self.format_metachar("}")}' if r < len(rules) - 1: report += f'{self.format_metachar(",")}{newline4 or space}' report += ( f'{newline2}{self.format_metachar("]")}' f'{newline0}{self.format_metachar("}")}' ) else: for d, (key, value) in enumerate(data.items()): report += ( f"{self.format_config_key(json.dumps(key))}" f'{self.format_metachar(":")}' ) if isinstance(value, list): report += f'{space}{self.format_metachar("[")}{newline4}' for i, value_item in enumerate(value): report += self.format_config_value( json.dumps(value_item), ) if i < len(value) - 1: report += ( f'{self.format_metachar(",")}' f"{newline4 or space}" ) else: report += f'{newline2}{self.format_metachar("]")}' else: report += f" {self.format_config_value(json.dumps(value))}" if d < len(data) - 1: report += f'{self.format_metachar(",")}{newline2 or space}' report += f'{newline0}{self.format_metachar("}")}' return report