def METHOD_NAME(
    cls, job_name_or_idx: str | int, yaml_path: t.Union[str, Path]
) -> t.Tuple[str, t.List[Step]]:
    # default run index 0 handler
    job_name = str(job_name_or_idx or "0")
    jobs = load_yaml(yaml_path)
    sorted_jobs = sorted(jobs.items())
    job = None
    try:
        if job_name in jobs:
            job = jobs[job_name]
        else:
            job_index = int(job_name)
            job_name, job = sorted_jobs[job_index]
    finally:
        console.print(":bank: runnable handlers:")
        for i, j in enumerate(sorted_jobs):
            flag = "" if job is None or job != j[1] else "*"
            console.print(f"\t {flag:2} [{i}]: {j[0]}")
    """
    - cls_name: MNISTInference
      concurrency: 1
      extra_args: []
      extra_kwargs: {}
      func_name: ppl
      name: mnist.evaluator:MNISTInference.ppl
      show_name: ppl
      needs: ["mnist.evaluator:MNISTInference.cmp"]
      module_name: mnist.evaluator
      replicas: 2
      resources: []
      expose: 0
      virtual: false
    """
    if not isinstance(job, list):
        raise TypeError(f"job must be a list, but got {job}")
    steps = []
    for v in job:
        step = Step(
            name=v["name"],
            show_name=v["show_name"],
            resources=v["resources"],
            needs=v["needs"],
            concurrency=v["concurrency"],
            task_num=v["replicas"],
            cls_name=v["cls_name"],
            module_name=v["module_name"],
            func_name=v["func_name"],
            extra_args=v.get("extra_args"),
            extra_kwargs=v.get("extra_kwargs"),
            expose=v.get("expose"),
            virtual=v.get("virtual"),
            require_dataset=v.get("require_dataset"),
        )
        steps.append(step)
    return job_name, steps