Skip to content

API Reference

The public entry point for programmatic usage is azure_functions_doctor.api.run_diagnostics(path, profile, rules_path). It uses the same diagnostics engine as azure-functions doctor, then returns structured results that can be consumed in scripts, CI pipelines, or custom tooling.

Public API at a Glance

API Purpose Typical usage
run_diagnostics(path, profile, rules_path) Run all checks and return section-level results. CI validation, custom wrappers, pre-commit hooks.
Doctor(path, profile, rules_path) Lower-level runner with explicit lifecycle methods. Advanced control over rule loading and execution.
CheckResult Result object for one check item. Output processing and custom reporting.
SectionResult Result object for a group of checks. Rendering grouped summaries by category.
Config Environment-backed runtime configuration container. Internal integration and test overrides.
HandlerRegistry Maps rule type to execution handlers. Handler extension and internal diagnostics flow.

Programmatic Usage with run_diagnostics

Use run_diagnostics when you want behavior that matches the CLI while staying inside Python code.

from pathlib import Path

from azure_functions_doctor.api import run_diagnostics


def summarize_failures(project_path: str) -> int:
    results = run_diagnostics(path=project_path, profile="full", rules_path=None)
    failed_required = 0

    for section in results:
        for item in section["items"]:
            if item["status"] == "fail":
                failed_required += 1

    return failed_required


if __name__ == "__main__":
    target = str(Path(".").resolve())
    failed = summarize_failures(target)
    raise SystemExit(1 if failed else 0)

Parameters

Parameter Type Required Description
path str Yes File system path to the Azure Functions app root.
profile str | None No "full" (default behavior) or "minimal" (required checks only).
rules_path pathlib.Path | None No Optional path to a custom rules file matching the rules schema.

Return Value

run_diagnostics returns list[SectionResult], where each section includes:

  • title: human-readable section title
  • category: machine-friendly section key
  • status: pass or fail at section level
  • items: list of CheckResult entries

Working with CheckResult and SectionResult

The following snippet shows safe access to optional fields (hint, hint_url) while creating a report.

from azure_functions_doctor.api import run_diagnostics


def flatten_results(path: str) -> list[dict[str, str]]:
    rows: list[dict[str, str]] = []
    for section in run_diagnostics(path=path, profile=None, rules_path=None):
        for item in section["items"]:
            rows.append(
                {
                    "section": section["category"],
                    "label": item["label"],
                    "status": item["status"],
                    "value": item["value"],
                    "hint": item.get("hint", ""),
                    "hint_url": item.get("hint_url", ""),
                }
            )
    return rows

Using Doctor Directly

Use Doctor if you need to separate rule loading, validation, and execution.

from pathlib import Path

from azure_functions_doctor.doctor import Doctor


def run_with_custom_rules(project_dir: str, custom_rules_file: str) -> list[dict]:
    doctor = Doctor(
        path=project_dir,
        profile="minimal",
        rules_path=Path(custom_rules_file),
    )
    rules = doctor.load_rules()
    return doctor.run_all_checks(rules=rules)

Configuration API (Config)

Config reads defaults and environment variables prefixed with FUNC_DOCTOR_. Common keys include:

  • FUNC_DOCTOR_LOG_LEVEL
  • FUNC_DOCTOR_LOG_FORMAT
  • FUNC_DOCTOR_MAX_FILE_SIZE_MB
  • FUNC_DOCTOR_SEARCH_TIMEOUT_SECONDS
  • FUNC_DOCTOR_OUTPUT_WIDTH
  • FUNC_DOCTOR_ENABLE_COLORS
  • FUNC_DOCTOR_PARALLEL_EXECUTION
from azure_functions_doctor.config import get_config, override_config


def configure_for_tests() -> dict:
    override_config(log_level="DEBUG", output_width=100, enable_colors=False)
    cfg = get_config()
    return cfg.to_dict()

Handler Registry Integration

HandlerRegistry stores the mapping from rule type to concrete handler methods. Most users do not need to call it directly, but it is useful in internal extensions.

from pathlib import Path

from azure_functions_doctor.handlers import HandlerRegistry


def run_single_rule(rule: dict, project_path: str) -> dict[str, str]:
    registry = HandlerRegistry()
    result = registry.handle(rule=rule, path=Path(project_path))
    return result

CLI

doctor(path='.', verbose=False, debug=False, format='table', output=None, profile=None, rules=None, summary_json=None)

Run diagnostics on an Azure Functions application.

Parameters:

Name Type Description Default
path str

Path to the Azure Functions app. Defaults to current directory.

'.'
verbose Annotated[bool, Option(-v, --verbose, help='Show detailed hints for failed checks')]

Show detailed hints for failed checks.

False
debug Annotated[bool, Option(help='Enable debug logging')]

Enable debug logging to stderr.

False
format Annotated[str, Option(help="Output format: 'table', 'json', 'sarif', or 'junit'")]

Output format: 'table', 'json', 'sarif', or 'junit'.

'table'
output Annotated[Optional[Path], Option(help='Optional path to save output result')]

Optional file path to save output result.

None
profile Annotated[Optional[str], Option(help="Rule profile: 'minimal' or 'full'")]

Optional rule profile ('minimal' or 'full').

None
rules Annotated[Optional[Path], Option(help='Optional path to a custom rules file')]

Optional path to a custom rules file.

None
summary_json Annotated[Optional[Path], Option(--summary - json, help='Write a JSON summary of counts (passed/warned/failed) to this path')]

Path to write a JSON summary with passed/warned/failed counts.

None
Source code in src/azure_functions_doctor/cli.py
@cli.command(name="doctor")
def doctor(
    path: str = ".",
    verbose: Annotated[
        bool, typer.Option("-v", "--verbose", help="Show detailed hints for failed checks")
    ] = False,
    debug: Annotated[bool, typer.Option(help="Enable debug logging")] = False,
    format: Annotated[
        str, typer.Option(help="Output format: 'table', 'json', 'sarif', or 'junit'")
    ] = "table",
    output: Annotated[
        Optional[Path], typer.Option(help="Optional path to save output result")
    ] = None,
    profile: Annotated[
        Optional[str], typer.Option(help="Rule profile: 'minimal' or 'full'")
    ] = None,
    rules: Annotated[
        Optional[Path], typer.Option(help="Optional path to a custom rules file")
    ] = None,
    summary_json: Annotated[
        Optional[Path],
        typer.Option(
            "--summary-json",
            help="Write a JSON summary of counts (passed/warned/failed) to this path",
        ),
    ] = None,
) -> None:
    """
    Run diagnostics on an Azure Functions application.

    Args:
        path: Path to the Azure Functions app. Defaults to current directory.
        verbose: Show detailed hints for failed checks.
        debug: Enable debug logging to stderr.
        format: Output format: 'table', 'json', 'sarif', or 'junit'.
        output: Optional file path to save output result.
        profile: Optional rule profile ('minimal' or 'full').
        rules: Optional path to a custom rules file.
        summary_json: Path to write a JSON summary with passed/warned/failed counts.
    """
    # Validate inputs before proceeding
    _validate_inputs(path, format, output)

    if rules is not None and not rules.exists():
        raise typer.BadParameter(f"Rules path does not exist: {rules}")

    # Configure logging based on CLI flags
    if debug:
        setup_logging(level="DEBUG", format_style="structured")
    else:
        # Use environment variable or default to WARNING
        setup_logging(level=None, format_style="simple")

    start_time = time.time()
    doctor = Doctor(path, profile=profile, rules_path=rules)
    resolved_path = Path(path).resolve()

    # Log diagnostic start
    loaded_rules = doctor.load_rules()
    log_diagnostic_start(str(resolved_path), len(loaded_rules))
    results = doctor.run_all_checks(rules=loaded_rules)

    # Calculate execution metrics
    end_time = time.time()
    duration_ms = (end_time - start_time) * 1000

    # Count results for logging
    total_checks = sum(len(section["items"]) for section in results)
    passed_items = sum(
        1 for section in results for item in section["items"] if item.get("status") == "pass"
    )
    failed_items = sum(
        1 for section in results for item in section["items"] if item.get("status") == "fail"
    )
    # Note: handlers currently only return "pass"/"fail", not "error"
    errors = 0

    # Log diagnostic completion
    log_diagnostic_complete(total_checks, passed_items, failed_items, errors, duration_ms)

    # Pre-compute aggregated counts from normalized item['status'] values
    passed_count = 0
    warning_count = 0  # explicit 'warn' statuses
    fail_count = 0  # explicit 'fail' statuses
    for section in results:
        for item in section["items"]:
            s = item.get("status")
            if s == "pass":
                passed_count += 1
            elif s == "warn":
                warning_count += 1
            elif s == "fail":
                fail_count += 1
            else:
                warning_count += 1  # unknown treated as warning

    # Write summary JSON sidecar when --summary-json is specified (format-independent)
    if summary_json is not None:
        summary_data = {
            "passed": passed_count,
            "warned": warning_count,
            "failed": fail_count,
        }
        try:
            summary_json.parent.mkdir(parents=True, exist_ok=True)
            summary_json.write_text(json.dumps(summary_data), encoding="utf-8")
        except (OSError, PermissionError) as exc:
            logger.warning(f"Failed to write summary JSON to {summary_json}: {exc}")

    if format == "json":
        generated_at = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
        metadata = {
            "tool_version": __version__,
            "generated_at": generated_at,
            "target_path": str(Path(path).resolve()),
        }
        json_output = {"metadata": metadata, "results": results}
        _write_output(json.dumps(json_output, indent=2), output, "JSON")
        raise typer.Exit(1 if fail_count > 0 else 0)

    if format == "sarif":
        # Build label → rule mapping for enriched ruleId and metadata
        label_to_rule = {r["label"]: r for r in loaded_rules}

        # Build driver.rules from the full loaded ruleset
        driver_rules = []
        for rule in loaded_rules:
            driver_rule: dict[str, object] = {
                "id": rule["id"],
                "name": rule["label"],
                "shortDescription": {"text": rule.get("description", rule["label"])},
                "properties": {
                    "category": rule.get("category", ""),
                    "required": rule.get("required", False),
                },
            }
            hint_url = rule.get("hint_url", "")
            if hint_url:
                driver_rule["helpUri"] = hint_url
            driver_rules.append(driver_rule)

        sarif_results = []
        for section in results:
            for item in section["items"]:
                status = item.get("status")
                if status == "pass":
                    continue
                label = item.get("label", "")
                matched_rule = label_to_rule.get(label)
                rule_id = matched_rule["id"] if matched_rule else label
                level = "error" if status == "fail" else "warning"
                sarif_result: dict[str, object] = {
                    "ruleId": rule_id,
                    "message": {"text": item.get("value", "")},
                    "level": level,
                    "locations": [
                        {
                            "physicalLocation": {
                                "artifactLocation": {
                                    "uri": path.replace("\\", "/").rstrip("/") + "/",
                                    "uriBaseId": "%SRCROOT%",
                                }
                            }
                        }
                    ],
                }
                if item.get("hint"):
                    sarif_result["properties"] = {"hint": item["hint"]}
                sarif_results.append(sarif_result)

        sarif_output = {
            "version": "2.1.0",
            "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
            "runs": [
                {
                    "tool": {
                        "driver": {
                            "name": "azure-functions-doctor",
                            "version": __version__,
                            "informationUri": "https://github.com/yeongseon/azure-functions-doctor",
                            "rules": driver_rules,
                        }
                    },
                    "results": sarif_results,
                }
            ],
        }
        _write_output(json.dumps(sarif_output, indent=2), output, "SARIF")
        raise typer.Exit(1 if fail_count > 0 else 0)

    if format == "junit":
        import xml.etree.ElementTree as ET  # nosec B405

        tests = 0
        failures = 0
        skipped = 0
        suite = ET.Element(
            "testsuite",
            name="func-doctor",
            tests="0",
            failures="0",
            skipped="0",
            time=f"{duration_ms / 1000:.3f}",
        )

        for section in results:
            for item in section["items"]:
                tests += 1
                case = ET.SubElement(
                    suite, "testcase", classname=section["title"], name=item.get("label", "")
                )
                status = item.get("status")
                if status == "fail":
                    failures += 1
                    failure = ET.SubElement(case, "failure", message=item.get("value", ""))
                    failure.text = item.get("hint", "")
                elif status == "warn":
                    skipped += 1
                    skipped_el = ET.SubElement(case, "skipped", message=item.get("value", ""))
                    skipped_el.text = item.get("hint", "")

        suite.set("tests", str(tests))
        suite.set("failures", str(failures))
        suite.set("skipped", str(skipped))
        junit_output = ET.tostring(suite, encoding="utf-8", xml_declaration=True).decode("utf-8")
        _write_output(junit_output, output, "JUnit")
        raise typer.Exit(1 if fail_count > 0 else 0)

    # Note: Top header removed per UI change; programming model header intentionally omitted

    if debug:
        console.print("[dim]Debug logging enabled - check stderr for detailed logs[/dim]\n")

    # Table-format user-facing output (requested design)
    console.print("Azure Functions Doctor   ")
    console.print(f"Path: {resolved_path}")

    # Print each section with simple title and items
    for section in results:
        console.print()
        console.print(section["title"])

        for item in section["items"]:
            label = item.get("label", "")
            value = item.get("value", "")
            status = item.get("status", "pass")
            icon = format_status_icon(status)

            # Compose main line: [ICON] Label: value (status)
            line = Text.assemble((f"[{icon}] ", "bold"), (label, "dim"))
            if value:
                line.append(": ")
                line.append(format_detail(status, value))

            # append status in parentheses for clarity on UI when non-pass
            if status != "pass":
                line.append(f" ({status})", "italic dim")

            console.print(line)

            # show hint as 'fix:' only when verbose is enabled
            if status != "pass" and verbose:
                hint = item.get("hint", "")
                if hint:
                    prefix = "↪ "
                    console.print(f"    {prefix}fix: {hint}")

    # Use the precomputed counts from earlier for final output
    console.print()
    # Print Doctor summary at the bottom like the requested sample
    console.print("Doctor summary (to see all details, run azure-functions doctor -v):")
    # Use singular/plural simple form as in sample (error vs errors)
    # Summary now reflects canonical statuses: fails, warnings, passed
    w_label = "warning" if warning_count == 1 else "warnings"
    f_label = "fail" if fail_count == 1 else "fails"
    # 'passed' label remains same for singular/plural in current design
    console.print(f"  {fail_count} {f_label}, {warning_count} {w_label}, {passed_count} passed")
    exit_code = 1 if fail_count > 0 else 0
    console.print(f"Exit code: {exit_code}")
    if exit_code != 0:
        raise typer.Exit(exit_code)

Doctor

Doctor(path='.', profile=None, rules_path=None)

Diagnostic runner for Azure Functions apps.

Loads checks from the built-in Azure Functions Python v2 rule asset located at azure_functions_doctor.assets.rules.v2.json.

Source code in src/azure_functions_doctor/doctor.py
def __init__(
    self,
    path: str = ".",
    profile: Optional[str] = None,
    rules_path: Optional[Path] = None,
) -> None:
    self.project_path: Path = Path(path).resolve()
    self.profile = profile
    self.rules_path: Optional[Path] = None
    if rules_path is not None:
        resolved = rules_path.resolve()
        if not resolved.is_file():
            raise ValueError(f"rules_path must be an existing file: {resolved}")
        self.rules_path = resolved
    self.programming_model = self._detect_programming_model()

load_rules()

Load and validate rules from a custom path or the built-in v2 ruleset.

Source code in src/azure_functions_doctor/doctor.py
def load_rules(self) -> list[Rule]:
    """Load and validate rules from a custom path or the built-in v2 ruleset."""
    if self.rules_path is not None:
        with self.rules_path.open(encoding="utf-8") as f:
            rules: list[Rule] = json.load(f)
    else:
        rules = self._load_v2_rules()

    self._validate_rules(rules)
    return sorted(rules, key=lambda r: r.get("check_order", 999))

Handlers

HandlerRegistry()

Registry for diagnostic check handlers with individual handler methods.

Source code in src/azure_functions_doctor/handlers.py
def __init__(self) -> None:
    self._handlers = {
        "compare_version": self._handle_compare_version,
        "env_var_exists": self._handle_env_var_exists,
        "path_exists": self._handle_path_exists,
        "file_exists": self._handle_file_exists,
        "package_installed": self._handle_package_installed,
        "package_declared": self._handle_package_declared,
        "source_code_contains": self._handle_source_code_contains,
        "conditional_exists": self._handle_conditional_exists,
        "callable_detection": self._handle_callable_detection,
        "executable_exists": self._handle_executable_exists,
        "any_of_exists": self._handle_any_of_exists,
        "file_glob_check": self._handle_file_glob_check,
        "host_json_property": self._handle_host_json_property,
        "host_json_version": self._handle_host_json_version,
        "local_settings_security": self._handle_local_settings_security,
        "host_json_extension_bundle_version": self._handle_host_json_extension_bundle_version,
        "package_forbidden": self._handle_package_forbidden,
    }

handle(rule, path)

Route rule execution to appropriate handler.

Source code in src/azure_functions_doctor/handlers.py
def handle(self, rule: Rule, path: Path) -> dict[str, str]:
    """Route rule execution to appropriate handler."""
    check_type = rule.get("type")
    if check_type is None:
        return _create_result("fail", "Missing check type in rule")
    handler = self._handlers.get(check_type)

    if not handler:
        return _create_result("fail", f"Unknown check type: {check_type}")

    try:
        return handler(rule, path)
    except Exception as exc:
        return _handle_specific_exceptions(f"executing {check_type} check", exc)

generic_handler(rule, path)

Execute a diagnostic rule based on its type and condition.

This function maintains backward compatibility while delegating to the registry.

Parameters:

Name Type Description Default
rule Rule

The diagnostic rule to execute.

required
path Path

Path to the Azure Functions project.

required

Returns:

Type Description
dict[str, str]

A dictionary with the status and detail of the check.

Source code in src/azure_functions_doctor/handlers.py
def generic_handler(rule: Rule, path: Path) -> dict[str, str]:
    """
    Execute a diagnostic rule based on its type and condition.

    This function maintains backward compatibility while delegating to the registry.

    Args:
        rule: The diagnostic rule to execute.
        path: Path to the Azure Functions project.

    Returns:
        A dictionary with the status and detail of the check.
    """
    return _registry.handle(rule, path)

Configuration

Configuration management for Azure Functions Doctor.

Environment variables with FUNC_DOCTOR_ prefix (e.g. FUNC_DOCTOR_LOG_LEVEL) are loaded into Config. These options are reserved for future use; the CLI currently configures logging via logging_config.setup_logging() and does not read from Config. When wiring Config into the CLI/Doctor (e.g. max_file_size_mb, search_timeout_seconds), update this module and the CLI entry point.

Config()

Centralized configuration management with environment variable support.

Options (max_file_size_mb, search_timeout_seconds, etc.) are for future use; not yet wired into the CLI or Doctor. Use get_config() to access the global instance.

Source code in src/azure_functions_doctor/config.py
def __init__(self) -> None:
    self._config: Dict[str, Any] = {}
    self._load_defaults()
    self._load_from_environment()

get(key, default=None)

Get configuration value by key.

Source code in src/azure_functions_doctor/config.py
def get(self, key: str, default: Any = None) -> Any:
    """Get configuration value by key."""
    return self._config.get(key, default)

get_custom_rules_path()

Get custom rules file path from environment.

Source code in src/azure_functions_doctor/config.py
def get_custom_rules_path(self) -> Optional[Path]:
    """Get custom rules file path from environment."""
    custom_path = os.getenv("FUNC_DOCTOR_CUSTOM_RULES")
    if custom_path:
        path = Path(custom_path)
        if path.exists():
            return path
        logger.warning(f"Custom rules path does not exist: {custom_path}")
    return None

get_log_format()

Get logging format style.

Source code in src/azure_functions_doctor/config.py
def get_log_format(self) -> str:
    """Get logging format style."""
    return str(self._config["log_format"])

get_log_level()

Get logging level.

Source code in src/azure_functions_doctor/config.py
def get_log_level(self) -> str:
    """Get logging level."""
    return str(self._config["log_level"])

get_max_file_size_mb()

Get maximum file size for processing in MB.

Source code in src/azure_functions_doctor/config.py
def get_max_file_size_mb(self) -> int:
    """Get maximum file size for processing in MB."""
    return int(self._config["max_file_size_mb"])

get_output_width()

Get output width for formatting.

Source code in src/azure_functions_doctor/config.py
def get_output_width(self) -> int:
    """Get output width for formatting."""
    return int(self._config["output_width"])

get_rules_file()

Get rules file name.

Source code in src/azure_functions_doctor/config.py
def get_rules_file(self) -> str:
    """Get rules file name."""
    return str(self._config["rules_file"])

get_search_timeout_seconds()

Get search operation timeout in seconds.

Source code in src/azure_functions_doctor/config.py
def get_search_timeout_seconds(self) -> int:
    """Get search operation timeout in seconds."""
    return int(self._config["search_timeout_seconds"])

is_colors_enabled()

Check if color output is enabled.

Source code in src/azure_functions_doctor/config.py
def is_colors_enabled(self) -> bool:
    """Check if color output is enabled."""
    return bool(self._config["enable_colors"])

is_parallel_execution_enabled()

Check if parallel execution is enabled.

Source code in src/azure_functions_doctor/config.py
def is_parallel_execution_enabled(self) -> bool:
    """Check if parallel execution is enabled."""
    return bool(self._config["parallel_execution"])

set(key, value)

Set configuration value.

Source code in src/azure_functions_doctor/config.py
def set(self, key: str, value: Any) -> None:
    """Set configuration value."""
    old_value = self._config.get(key)
    self._config[key] = value
    logger.debug(f"Configuration changed: {key}={old_value} -> {value}")

to_dict()

Return configuration as dictionary.

Source code in src/azure_functions_doctor/config.py
def to_dict(self) -> Dict[str, Any]:
    """Return configuration as dictionary."""
    return self._config.copy()

get_config()

Get the global configuration instance.

Source code in src/azure_functions_doctor/config.py
def get_config() -> Config:
    """Get the global configuration instance."""
    return config

override_config(**kwargs)

Override configuration values (useful for testing).

Source code in src/azure_functions_doctor/config.py
def override_config(**kwargs: Any) -> None:
    """Override configuration values (useful for testing)."""
    for key, value in kwargs.items():
        config.set(key, value)

Target Resolver

resolve_target_value(target)

Resolve the current value of a target used in version comparison or diagnostics.

Parameters:

Name Type Description Default
target str

The name of the target to resolve. Examples include "python" or "func_core_tools".

required

Returns:

Type Description
str

A string representing the resolved version or value.

Raises:

Type Description
ValueError

If the target is not recognized.

Source code in src/azure_functions_doctor/target_resolver.py
def resolve_target_value(target: str) -> str:
    """
    Resolve the current value of a target used in version comparison or diagnostics.

    Args:
        target: The name of the target to resolve. Examples include "python" or "func_core_tools".

    Returns:
        A string representing the resolved version or value.

    Raises:
        ValueError: If the target is not recognized.
    """
    if target == "python":
        return sys.version.split()[0]
    if target == "func_core_tools":
        func_path = shutil.which("func")
        if not func_path:
            logger.debug("Azure Functions Core Tools not found in PATH")
            return "not_installed"
        try:
            output = subprocess.check_output([func_path, "--version"], text=True, timeout=10)  # nosec B603
            return output.strip()
        except FileNotFoundError:
            logger.debug("Azure Functions Core Tools executable disappeared before execution")
            return "not_installed"
        except subprocess.TimeoutExpired:
            logger.warning("Timeout getting func version")
            return "timeout"
        except TimeoutError:
            logger.warning("Timeout getting func version")
            return "timeout"
        except subprocess.CalledProcessError as e:
            logger.warning(f"func command failed with code {e.returncode}")
            return f"error_{e.returncode}"
        except Exception as exc:
            logger.error(f"Unexpected error getting func version: {exc}")
            return "unknown_error"
    raise ValueError(f"Unknown target: {target}")

Utility

format_detail(status, value)

Return a colored Text element based on status and value.

Parameters:

Name Type Description Default
status str

Diagnostic status ("pass", "fail", "warn").

required
value str

Text to display, typically a description.

required

Returns:

Type Description
Text

A Rich Text object styled with status color.

Source code in src/azure_functions_doctor/utils.py
def format_detail(status: str, value: str) -> Text:
    """
    Return a colored Text element based on status and value.

    Args:
        status: Diagnostic status ("pass", "fail", "warn").
        value: Text to display, typically a description.

    Returns:
        A Rich Text object styled with status color.
    """
    color = DETAIL_COLOR_MAP.get(status, "white")
    return Text(value, style=color)

format_result(status)

Return a styled icon Text element based on status.

Parameters:

Name Type Description Default
status str

Diagnostic status ("pass", "fail", "warn").

required

Returns:

Type Description
Text

A Rich Text object with icon and style for headers.

Source code in src/azure_functions_doctor/utils.py
def format_result(status: str) -> Text:
    """
    Return a styled icon Text element based on status.

    Args:
        status: Diagnostic status ("pass", "fail", "warn").

    Returns:
        A Rich Text object with icon and style for headers.
    """
    style = STATUS_STYLES.get(status, Style(color="white"))
    icon = format_status_icon(status)
    return Text(icon, style=style)

format_status_icon(status)

Return a simple icon character based on status.

Parameters:

Name Type Description Default
status str

Diagnostic status ("pass", "fail", "warn").

required

Returns: A string icon such as ✓, !, or ✗.

Source code in src/azure_functions_doctor/utils.py
def format_status_icon(status: str) -> str:
    """
    Return a simple icon character based on status.

    Args:
        status: Diagnostic status ("pass", "fail", "warn").

    Returns:
    A string icon such as ✓, !, or ✗.
    """
    return STATUS_ICONS.get(status, "?")