From ff17f900985e06e539eedd971a979a248c70f857 Mon Sep 17 00:00:00 2001 From: "dingfeng.wong" Date: Thu, 10 Jul 2025 00:30:52 +0800 Subject: [PATCH] factor --- src/elf/grafana_cli.py | 182 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 160 insertions(+), 22 deletions(-) diff --git a/src/elf/grafana_cli.py b/src/elf/grafana_cli.py index 0679c88..b3fdce1 100644 --- a/src/elf/grafana_cli.py +++ b/src/elf/grafana_cli.py @@ -2,8 +2,9 @@ import typer from rich.console import Console import json import pyperclip -from typing import Dict, Any, List, Optional +from typing import Dict, Any, List, Optional, Callable from pathlib import Path +import re console = Console() @@ -14,6 +15,32 @@ def safe_get(data: Dict[str, Any], key: str, default: Any = None) -> Any: """Safely get a value from a dictionary.""" return data.get(key, default) +def contains_chinese(text: str) -> bool: + """Check if text contains Chinese characters.""" + if not isinstance(text, str): + return False + # Unicode ranges for Chinese characters + chinese_pattern = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf\u20000-\u2a6df\u2a700-\u2b73f\u2b740-\u2b81f\u2b820-\u2ceaf\uf900-\ufaff\u3300-\u33ff\ufe30-\ufe4f\uf900-\ufaff\u2f800-\u2fa1f]') + return bool(chinese_pattern.search(text)) + +def mutate_chinese_titles(data: Dict[str, Any]) -> None: + """Recursively mutate titles containing Chinese characters.""" + if not isinstance(data, dict): + return + + # List of keys that might contain title text + title_keys = ['title', 'name', 'description', 'tooltip', 'legendFormat', 'text'] + + for key, value in data.items(): + if key in title_keys and isinstance(value, str) and contains_chinese(value): + data[key] = "please_translate_me" + elif isinstance(value, dict): + mutate_chinese_titles(value) + elif isinstance(value, list): + for item in value: + if isinstance(item, dict): + mutate_chinese_titles(item) + def mutate_panel(panel: Dict[str, Any]) -> None: """Mutate a single panel by setting repeat and repeatDirection fields.""" # Check if type is "row" and remove repeat key if it exists @@ -40,7 +67,7 @@ def mutate_panels_recursive(panels: List[Dict[str, Any]]) -> None: if nested_panels and isinstance(nested_panels, list): mutate_panels_recursive(nested_panels) -def mutate_grafana_json(data: Dict[str, Any]) -> Dict[str, Any]: +def mutate_grafana_json_repeat(data: Dict[str, Any]) -> Dict[str, Any]: """ Mutate Grafana JSON by setting repeat and repeatDirection fields. @@ -61,25 +88,62 @@ def mutate_grafana_json(data: Dict[str, Any]) -> Dict[str, Any]: return mutated_data -@grafana_app.command("mutate", short_help="Mutate Grafana JSON to set repeat fields.") -def mutate_dashboard( - input_file: Optional[Path] = typer.Option( - None, "--input-file", "-i", help="Input JSON file path. If not provided, reads from clipboard." - ), - output_file: Optional[Path] = typer.Option( - None, "--output-file", "-o", help="Output JSON file path. If not provided, outputs to clipboard." - ) -): +def mutate_grafana_json_chinese(data: Dict[str, Any]) -> Dict[str, Any]: """ - Mutate Grafana JSON by setting repeat="instance" and repeatDirection="h". + Mutate Grafana JSON by replacing Chinese text in titles with 'please_translate_me'. - This command processes Grafana dashboard JSON and modifies panels to: - - Set repeat field to "instance" - - Set repeatDirection field to "h" - - Set maxPerRow to 12 - - Remove repeat field from row-type panels + Args: + data: The Grafana dashboard JSON data + + Returns: + The mutated JSON data """ - console.print("[blue]Processing Grafana dashboard JSON...[/blue]") + # Make a copy to avoid mutating the original + mutated_data = json.loads(json.dumps(data)) + + # Apply Chinese title mutation recursively + mutate_chinese_titles(mutated_data) + + return mutated_data + +def mutate_grafana_json_all(data: Dict[str, Any]) -> Dict[str, Any]: + """ + Apply both mutations: repeat fields and Chinese title translation. + + Args: + data: The Grafana dashboard JSON data + + Returns: + The mutated JSON data + """ + # First apply repeat field mutation + mutated_data = mutate_grafana_json_repeat(data) + console.print("[green]✓ Applied repeat field mutation[/green]") + + # Then apply Chinese title translation + mutated_data = mutate_grafana_json_chinese(mutated_data) + console.print("[green]✓ Applied Chinese title translation[/green]") + + return mutated_data + +def process_grafana_json( + mutation_func: Callable[[Dict[str, Any]], Dict[str, Any]], + input_file: Optional[Path], + output_file: Optional[Path], + process_message: str, + success_message: str +) -> None: + """ + Common function to process Grafana JSON with input/output handling. + + Args: + mutation_func: Function to apply mutations to the JSON data + input_file: Optional input file path + output_file: Optional output file path + process_message: Message to display when starting processing + success_message: Message to display when mutation succeeds + """ + console.print(f"[blue]{process_message}[/blue]") # Read input try: @@ -107,10 +171,10 @@ def mutate_dashboard( console.print(f"[red]Error parsing JSON: {e}[/red]") raise typer.Exit(code=1) - # Mutate the data + # Apply mutation try: - mutated_data = mutate_grafana_json(data) - console.print("[green]Successfully mutated Grafana JSON![/green]") + mutated_data = mutation_func(data) + console.print(f"[green]{success_message}[/green]") except Exception as e: console.print(f"[red]Error mutating JSON: {e}[/red]") raise typer.Exit(code=1) @@ -129,4 +193,78 @@ def mutate_dashboard( console.print("[green]Output copied to clipboard![/green]") except Exception as e: console.print(f"[red]Error writing output: {e}[/red]") - raise typer.Exit(code=1) \ No newline at end of file + raise typer.Exit(code=1) + +@grafana_app.command("mutate", short_help="Mutate Grafana JSON to set repeat fields.") +def mutate_dashboard( + input_file: Optional[Path] = typer.Option( + None, "--input-file", "-i", help="Input JSON file path. If not provided, reads from clipboard." + ), + output_file: Optional[Path] = typer.Option( + None, "--output-file", "-o", help="Output JSON file path. If not provided, outputs to clipboard." + ) +): + """ + Mutate Grafana JSON by setting repeat="instance" and repeatDirection="h". + + This command processes Grafana dashboard JSON and modifies panels to: + - Set repeat field to "instance" + - Set repeatDirection field to "h" + - Set maxPerRow to 12 + - Remove repeat field from row-type panels + """ + process_grafana_json( + mutation_func=mutate_grafana_json_repeat, + input_file=input_file, + output_file=output_file, + process_message="Processing Grafana dashboard JSON...", + success_message="Successfully mutated Grafana JSON!" + ) + +@grafana_app.command("translate", short_help="Replace Chinese text in titles with 'please_translate_me'.") +def translate_dashboard( + input_file: Optional[Path] = typer.Option( + None, "--input-file", "-i", help="Input JSON file path. If not provided, reads from clipboard." + ), + output_file: Optional[Path] = typer.Option( + None, "--output-file", "-o", help="Output JSON file path. If not provided, outputs to clipboard." + ) +): + """ + Replace Chinese text in titles with 'please_translate_me'. + + This command processes Grafana dashboard JSON and replaces any Chinese characters + in title-related fields (title, name, description, tooltip, legendFormat, text) + with the placeholder text 'please_translate_me'. + """ + process_grafana_json( + mutation_func=mutate_grafana_json_chinese, + input_file=input_file, + output_file=output_file, + process_message="Processing Grafana dashboard JSON for Chinese title translation...", + success_message="Successfully replaced Chinese text in titles!" + ) + +@grafana_app.command("mutate-all", short_help="Apply both repeat field mutation and Chinese title translation.") +def mutate_all_dashboard( + input_file: Optional[Path] = typer.Option( + None, "--input-file", "-i", help="Input JSON file path. If not provided, reads from clipboard." + ), + output_file: Optional[Path] = typer.Option( + None, "--output-file", "-o", help="Output JSON file path. If not provided, outputs to clipboard." + ) +): + """ + Apply both mutations: set repeat fields and replace Chinese text in titles. + + This command processes Grafana dashboard JSON and applies both: + 1. Repeat field mutation (repeat="instance", repeatDirection="h", maxPerRow=12) + 2. Chinese title translation (replaces Chinese characters with 'please_translate_me') + """ + process_grafana_json( + mutation_func=mutate_grafana_json_all, + input_file=input_file, + output_file=output_file, + process_message="Processing Grafana dashboard JSON with all mutations...", + success_message="Successfully applied all mutations!" + ) \ No newline at end of file