Repository: apache/airflow
File: scripts/ci/prek/check_airflowctl_command_coverage.py (Python)

Code before:
    "bulk",
}

EXCLUDED_COMMANDS = {
    "assets delete-dag-queued-events",
    "assets delete-queued-event",
    "assets delete-queued-events",
    "assets get-by-alias",
    "assets get-dag-queued-event",
    "assets get-dag-queued-events",
    "assets get-queued-events",
    "assets list-by-alias",
    "assets materialize",
    "backfill cancel",
    "backfill create",
    "backfill create-dry-run",
    "backfill get",
    "backfill pause",
    "backfill unpause",
    "connections create-defaults",
    "connections test",
    "dags delete",
    "dags get-import-error",
    "dags get-tags",
    "pools export",  # Export only available via local Airflow CLI
    "variables export",  # Export only available via local Airflow CLI
}


def parse_operations() -> dict[str, list[str]]:
    commands: dict[str, list[str]] = {}

    with open(OPERATIONS_FILE) as f:
        tree = ast.parse(f.read(), filename=str(OPERATIONS_FILE))

    for node in ast.walk(tree):
        if isinstance(node, ast.ClassDef) and node.name.endswith("Operations"):
            if node.name in EXCLUDED_OPERATION_CLASSES:
                continue

            group_name = node.name.replace("Operations", "").lower()
            commands[group_name] = []

            for child in node.body:
                if isinstance(child, ast.FunctionDef):
                    method_name = child.name
                    if method_name in EXCLUDED_METHODS or method_name.startswith("_"):
                        continue
                    subcommand = method_name.replace("_", "-")
                    commands[group_name].append(subcommand)


Review comment (suggestion):
```suggestion
    "pools export",
    "variables export",
```

Code after:
    "bulk",
    "export",
}

EXCLUDED_COMMANDS = {
    "assets delete-dag-queued-events",
    "assets delete-queued-event",
    "assets delete-queued-events",
    "assets get-by-alias",
    "assets get-dag-queued-event",
    "assets get-dag-queued-events",
    "assets get-queued-events",
    "assets list-by-alias",
    "assets materialize",
    "backfill cancel",
    "backfill create",
    "backfill create-dry-run",
    "backfill get",
    "backfill pause",
    "backfill unpause",
    "connections create-defaults",
    "connections test",
    "dags delete",
    "dags get-import-error",
    "dags get-tags",
}


def parse_operations() -> dict[str, list[str]]:
    commands: dict[str, list[str]] = {}

    with open(OPERATIONS_FILE) as f:
        tree = ast.parse(f.read(), filename=str(OPERATIONS_FILE))

    for node in ast.walk(tree):
        if isinstance(node, ast.ClassDef) and node.name.endswith("Operations"):
            if node.name in EXCLUDED_OPERATION_CLASSES:
                continue

            group_name = node.name.replace("Operations", "").lower()
            commands[group_name] = []

            for child in node.body:
                if isinstance(child, ast.FunctionDef):
                    method_name = child.name
                    if method_name in EXCLUDED_METHODS or method_name.startswith("_"):
                        continue
                    subcommand = method_name.replace("_", "-")
                    commands[group_name].append(subcommand)

    return commands