diff --git a/swh/scanner/output.py b/swh/scanner/output.py index 86cd485..6a2607a 100644 --- a/swh/scanner/output.py +++ b/swh/scanner/output.py @@ -1,108 +1,108 @@ # Copyright (C) 2021 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from enum import Enum import json import os import sys from typing import Any import ndjson from swh.model.from_disk import Directory from .dashboard.dashboard import run_app from .data import MerkleNodeInfo, get_directory_data from .plot import generate_sunburst, offline_plot DEFAULT_OUTPUT = "text" class Color(Enum): BLUE = "\033[94m" GREEN = "\033[92m" RED = "\033[91m" END = "\033[0m" def colorize(text: str, color: Color): return color.value + text + Color.END.value class Output: def __init__( self, root_path: str, nodes_data: MerkleNodeInfo, source_tree: Directory ): self.root_path = root_path self.nodes_data = nodes_data self.source_tree = source_tree def show(self, mode=DEFAULT_OUTPUT): if mode == "text": isatty = sys.stdout.isatty() self.print_text(isatty) elif mode == "sunburst": directory_data = get_directory_data( self.root_path, self.source_tree, self.nodes_data ) sunburst_figure = generate_sunburst(directory_data, self.root_path) offline_plot(sunburst_figure) elif mode == "interactive": directory_data = get_directory_data( self.root_path, self.source_tree, self.nodes_data ) sunburst_figure = generate_sunburst(directory_data, self.root_path) run_app(sunburst_figure, self.source_tree, self.nodes_data) elif mode == "json": self.print_json() elif mode == "ndjson": self.print_ndjson() else: raise Exception(f"mode {mode} is not an output format") def get_path_name(self, node): return "path" if "path" in node.data.keys() else "data" def print_text(self, isatty: bool) -> None: def compute_level(node): node_path = str(node.data[self.get_path_name(node)]).split("/") source_path = str(self.source_tree.data["path"]).split("/") return len(node_path) - len(source_path) for node in self.source_tree.iter_tree(): self.print_node(node, isatty, compute_level(node)) def print_node(self, node: Any, isatty: bool, level: int) -> None: rel_path = os.path.basename(node.data[self.get_path_name(node)]) rel_path = rel_path.decode() begin = "│ " * level end = "/" if node.object_type == "directory" else "" if isatty: - if not self.nodes_data[str(node.swhid())]["known"]: + if not self.nodes_data[node.swhid()]["known"]: rel_path = colorize(rel_path, Color.RED) elif node.object_type == "directory": rel_path = colorize(rel_path, Color.BLUE) elif node.object_type == "content": rel_path = colorize(rel_path, Color.GREEN) print(f"{begin}{rel_path}{end}") def data_as_json(self): json = {} for node in self.source_tree.iter_tree(): node_known = self.nodes_data[node.swhid()]["known"] rel_path = os.path.relpath( node.data[self.get_path_name(node)].decode(), self.source_tree.data["path"].decode(), ) json[rel_path] = {"swhid": str(node.swhid()), "known": node_known} return json def print_json(self): print(json.dumps(self.data_as_json(), indent=4, sort_keys=True)) def print_ndjson(self): print(ndjson.dumps({k: v} for k, v in self.data_as_json().items()))