Repository: psf/black
File: src/black_primer/cli.py (Python)

Code before:
    ctx: Optional[click.core.Context],
    param: Optional[Union[click.core.Option, click.core.Parameter]],
    debug: Union[bool, int, str],
) -> Union[bool, int, str]:
    """Turn on debugging if asked otherwise INFO default"""
    log_level = logging.DEBUG if debug else logging.INFO
    logging.basicConfig(
        format="[%(asctime)s] %(levelname)s: %(message)s (%(filename)s:%(lineno)d)",
        level=log_level,
    )
    return debug


async def async_main(
    config: str,
    debug: bool,
    keep: bool,
    long_checkouts: bool,
    no_diff: bool,
    projects: str,
    rebase: bool,
    workdir: str,
    workers: int,
) -> int:
    work_path = Path(workdir)
    projects_to_run = set(p for p in projects.split(",")) if projects else None
    if not work_path.exists():
        LOG.debug(f"Creating {work_path}")
        work_path.mkdir()

    if not which("black"):
        LOG.error("Can not find 'black' executable in PATH. No point in running")
        return -1

    try:
        ret_val = await lib.process_queue(
            config,
            work_path,
            workers,
            keep,
            long_checkouts,
            rebase,
            no_diff,
            projects_to_run,
        )
        return int(ret_val)
    finally:
        if not keep and work_path.exists():
            LOG.debug(f"Removing {work_path}")
            rmtree(work_path, onerror=lib.handle_PermissionError)


Review comment (refactor):
Either (1) move this to click option `default=` so that others can see which projects exist when getting `help` on this option, or (2) if no options are selected maybe we can add a prompt (which can ignored with `--projects all`) `Run all projects?` (better message than that) or they put the numbers of the selected projects like:

```
Select which projects (space separated) to run black_primer with:
1) django
2) black
3) pyramid
or enter to select all options
```

Code after:
def _handle_debug(
    ctx: Optional[click.core.Context],
    param: Optional[Union[click.core.Option, click.core.Parameter]],
    debug: Union[bool, int, str],
) -> Union[bool, int, str]:
    """Turn on debugging if asked otherwise INFO default"""
    log_level = logging.DEBUG if debug else logging.INFO
    logging.basicConfig(
        format="[%(asctime)s] %(levelname)s: %(message)s (%(filename)s:%(lineno)d)",
        level=log_level,
    )
    return debug


def load_projects(config_path: Path) -> List[str]:
    with open(config_path) as config:
        return sorted(json.load(config)["projects"].keys())


# Unfortunately does import time file IO - but appears to be the only
# way to get `black-primer --help` to show projects list
DEFAULT_PROJECTS = load_projects(DEFAULT_CONFIG)


def _projects_callback(
    ctx: click.core.Context,
    param: Optional[Union[click.core.Option, click.core.Parameter]],
    projects: str,
) -> List[str]:
    requested_projects = set(projects.split(","))
    available_projects = set(
        DEFAULT_PROJECTS
        if str(DEFAULT_CONFIG) == ctx.params["config"]
        else load_projects(ctx.params["config"])
    )

    unavailable = requested_projects - available_projects
    if unavailable:
        LOG.error(f"Projects not found: {unavailable}. Available: {available_projects}")

    return sorted(requested_projects & available_projects)


async def async_main(
    config: str,
    debug: bool,
    keep: bool,
    long_checkouts: bool,
    no_diff: bool,
    projects: List[str],
    rebase: bool,