from typing import Optional import typer from wasabi import Printer, diff_strings, MarkdownRenderer from pathlib import Path from thinc.api import Config from ._util import debug_cli, Arg, Opt, show_validation_error, parse_config_overrides from ..util import load_config from .init_config import init_config, Optimizations @debug_cli.command( "diff-config", context_settings={"allow_extra_args": True, "ignore_unknown_options": True}, ) def debug_diff_cli( # fmt: off ctx: typer.Context, config_path: Path = Arg(..., help="Path to config file", exists=True, allow_dash=True), compare_to: Optional[Path] = Opt(None, help="Path to a config file to diff against, or `None` to compare against default settings", exists=True, allow_dash=True), optimize: Optimizations = Opt(Optimizations.efficiency.value, "--optimize", "-o", help="Whether the user config was optimized for efficiency or accuracy. Only relevant when comparing against the default config."), gpu: bool = Opt(False, "--gpu", "-G", help="Whether the original config can run on a GPU. Only relevant when comparing against the default config."), pretraining: bool = Opt(False, "--pretraining", "--pt", help="Whether to compare on a config with pretraining involved. Only relevant when comparing against the default config."), markdown: bool = Opt(False, "--markdown", "-md", help="Generate Markdown for GitHub issues") # fmt: on ): """Show a diff of a config file with respect to spaCy's defaults or another config file. If additional settings were used in the creation of the config file, then you must supply these as extra parameters to the command when comparing to the default settings. The generated diff can also be used when posting to the discussion forum to provide more information for the maintainers. The `optimize`, `gpu`, and `pretraining` options are only relevant when comparing against the default configuration (or specifically when `compare_to` is None). DOCS: https://spacy.io/api/cli#debug-diff """ debug_diff( config_path=config_path, compare_to=compare_to, gpu=gpu, optimize=optimize, pretraining=pretraining, markdown=markdown, ) def debug_diff( config_path: Path, compare_to: Optional[Path], gpu: bool, optimize: Optimizations, pretraining: bool, markdown: bool, ): msg = Printer() with show_validation_error(hint_fill=False): user_config = load_config(config_path) if compare_to: other_config = load_config(compare_to) else: # Recreate a default config based from user's config lang = user_config["nlp"]["lang"] pipeline = list(user_config["nlp"]["pipeline"]) msg.info(f"Found user-defined language: '{lang}'") msg.info(f"Found user-defined pipelines: {pipeline}") other_config = init_config( lang=lang, pipeline=pipeline, optimize=optimize.value, gpu=gpu, pretraining=pretraining, silent=True, ) user = user_config.to_str() other = other_config.to_str() if user == other: msg.warn("No diff to show: configs are identical") else: diff_text = diff_strings(other, user, add_symbols=markdown) if markdown: md = MarkdownRenderer() md.add(md.code_block(diff_text, "diff")) print(md.text) else: print(diff_text)