mirror of https://github.com/explosion/spaCy.git
101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
|
from typing import List, Dict
|
||
|
import typer
|
||
|
import srsly
|
||
|
from pathlib import Path
|
||
|
import os
|
||
|
import subprocess
|
||
|
import sys
|
||
|
from wasabi import msg
|
||
|
import shlex
|
||
|
|
||
|
from ._app import app, Arg, Opt
|
||
|
from .. import about
|
||
|
from ..schemas import ProjectConfigSchema, validate
|
||
|
|
||
|
CONFIG_FILE = "project.yml"
|
||
|
SUBDIRS = [
|
||
|
"assets",
|
||
|
"configs",
|
||
|
"packages",
|
||
|
"metrics",
|
||
|
"scripts",
|
||
|
"notebooks",
|
||
|
"training",
|
||
|
]
|
||
|
|
||
|
|
||
|
project_cli = typer.Typer(help="Command-line interface for spaCy projects")
|
||
|
|
||
|
|
||
|
def load_project_config(path):
|
||
|
config_path = path / CONFIG_FILE
|
||
|
if not config_path.exists():
|
||
|
msg.fail("Can't find project config", config_path, exits=1)
|
||
|
config = srsly.read_yaml(config_path)
|
||
|
errors = validate(ProjectConfigSchema, config)
|
||
|
if errors:
|
||
|
msg.fail(f"Invalid project config in {CONFIG_FILE}", "\n".join(errors), exits=1)
|
||
|
return config
|
||
|
|
||
|
|
||
|
def create_dirs(project_dir: Path):
|
||
|
for subdir in SUBDIRS:
|
||
|
(project_dir / subdir).mkdir(parents=True)
|
||
|
|
||
|
|
||
|
def run_cmd(command: str):
|
||
|
status = subprocess.call(shlex.split(command), env=os.environ.copy())
|
||
|
if status != 0:
|
||
|
sys.exit(status)
|
||
|
|
||
|
|
||
|
def run_commands(commands: List[str] = tuple(), variables: Dict[str, str] = {}):
|
||
|
for command in commands:
|
||
|
# Substitute variables, e.g. "./{NAME}.json"
|
||
|
command = command.format(**variables)
|
||
|
msg.info(command)
|
||
|
run_cmd(command)
|
||
|
|
||
|
|
||
|
@project_cli.command("clone")
|
||
|
def project_clone(
|
||
|
# fmt: off
|
||
|
name: str = Arg(..., help="The name of the template to fetch"),
|
||
|
dest: Path = Arg(Path.cwd(), help="Where to download and work. Defaults to current working directory.", exists=True, file_okay=False),
|
||
|
repo: str = Opt(about.__projects__, "--repo", "-r", help="The repository to look in."),
|
||
|
# fmt: on
|
||
|
):
|
||
|
"""Clone a project template from a repository."""
|
||
|
print("Cloning", repo)
|
||
|
|
||
|
|
||
|
@project_cli.command("run")
|
||
|
def project_run(
|
||
|
# fmt: off
|
||
|
project_dir: Path = Arg(..., help="Location of project directory", exists=True, file_okay=False),
|
||
|
subcommand: str = Arg(None, help="Name of command defined in project config")
|
||
|
# fmt: on
|
||
|
):
|
||
|
"""Run scripts defined in the project."""
|
||
|
config = load_project_config(project_dir)
|
||
|
config_commands = config.get("commands", [])
|
||
|
variables = config.get("variables", {})
|
||
|
commands = {cmd["name"]: cmd for cmd in config_commands}
|
||
|
if subcommand is None:
|
||
|
all_commands = config.get("run", [])
|
||
|
if not all_commands:
|
||
|
msg.warn("No run commands defined in project config", exits=0)
|
||
|
msg.table([(cmd["name"], cmd.get("help", "")) for cmd in config_commands])
|
||
|
for command in all_commands:
|
||
|
if command not in commands:
|
||
|
msg.fail(f"Can't find command '{command}' in project config", exits=1)
|
||
|
msg.divider(command)
|
||
|
run_commands(commands[command]["script"], variables)
|
||
|
return
|
||
|
if subcommand not in commands:
|
||
|
msg.fail(f"Can't find command '{subcommand}' in project config", exits=1)
|
||
|
run_commands(commands[subcommand]["script"], variables)
|
||
|
|
||
|
|
||
|
app.add_typer(project_cli, name="project")
|