Module ds.args

Parse command-line arguments.

Classes

class Args (help: bool = False, version: bool = False, debug: bool = False, dry_run: bool = False, no_config: bool = False, no_project: bool = False, list_: bool = False, cwd: Optional[Path] = None, env: Dict[str, str] = <factory>, env_file: Optional[Path] = None, file: Optional[Path] = None, workspace: List[str] = <factory>, pre: bool = False, post: bool = False, task: Task = <factory>)

Type-checked arguments.

Expand source code
@dataclass
class Args:
    """Type-checked arguments."""

    help: bool = False
    """Whether to show the usage."""

    version: bool = False
    """Whether to show the version."""

    debug: bool = False
    """Whether to show debug messages"""

    dry_run: bool = False
    """Whether to skip actually running tasks."""

    no_config: bool = False
    """Disable searching for config."""

    no_project: bool = False
    """Disable searching for project dependencies (`.venv`, `node_modules`)."""

    list_: bool = False
    """Whether to show available tasks"""

    cwd: Optional[Path] = None
    """Path to run tasks in."""

    env: Dict[str, str] = field(default_factory=dict)
    """Environment variable overrides."""

    env_file: Optional[Path] = None
    """Path to environment variables."""

    file: Optional[Path] = None
    """Path to task definitions."""

    workspace: List[str] = field(default_factory=list)
    """List of workspace patterns to run tasks in."""

    pre: bool = False
    """EXPERIMENTAL: Whether to run pre- tasks."""

    post: bool = False
    """EXPERIMENTAL: Whether to run post- tasks."""

    task: Task = field(default_factory=Task)
    """A composite task for the tasks given on the command-line."""

    def copy(self) -> Args:
        """Return a copy of this object."""
        return dataclasses.replace(self)

    def as_argv(self) -> List[str]:
        """Return args as a string."""
        result = ["ds"]

        # bool
        for option in [
            "--help",
            "--version",
            "--debug",
            "--dry-run",
            "--no-config",
            "--no-project",
            "--pre",
            "--post",
        ]:
            if getattr(self, _opt_prop(option)):
                result.append(option)
        if self.list_:
            result.append("--list")

        # path
        for option in ["--cwd", "--env-file", "--file"]:
            value = getattr(self, _opt_prop(option))
            if value:
                result.extend([option, str(value)])

        # workspace
        if self.workspace:
            for w in self.workspace:
                result.extend(["--workspace", w])

        # env
        for key, val in self.env.items():
            result.extend(["--env", f"'{key}={val}'"])

        # tasks
        for t in self.task.depends:
            parts = join([t.cmd, *t.args])
            result.append(parts)
        return result

    @staticmethod
    def parse(argv: List[str]) -> Args:
        """Parse command-line arguments in a docopt-like way."""
        args = Args()
        tasks: List[str] = []
        task_cmd = ""
        is_ours = True
        is_task_arg = False
        while argv:
            arg = argv.pop(0)
            if is_ours:
                # bool
                if arg in [
                    "--help",
                    "--version",
                    "--debug",
                    "--dry-run",
                    "--no-config",
                    "--no-project",
                    "--pre",
                    "--post",
                ]:
                    attr = _opt_prop(arg)
                    setattr(args, attr, True)
                elif arg == "-h":
                    args.help = True
                elif arg in ["-l", "--list"]:
                    args.list_ = True

                # path
                elif arg in ["--cwd", "--env-file", "--file"]:
                    attr = _opt_prop(arg)
                    setattr(args, attr, Path(argv.pop(0)).resolve())
                elif arg == "-f":
                    args.file = Path(argv.pop(0)).resolve()

                # other
                elif arg in ["-e", "--env"]:
                    key, val = argv.pop(0).split("=")
                    args.env[key] = val
                elif arg in ["-w", "--workspace"]:
                    args.workspace.append(argv.pop(0))
                elif arg == "-w*":  # special shorthand
                    args.workspace.append("*")
                else:
                    is_ours = False

            if is_ours:
                continue  # processed
            # our args processed

            if task_cmd and arg == ARG_BEG:  # explicit arg start
                is_task_arg = True
                continue  # not an argument

            if arg == ARG_END:  # explicit arg end
                task_cmd, is_task_arg = "", False
                continue  # not an argument

            if task_cmd and arg.startswith(ARG_OPTION):  # implicit arg start
                is_task_arg = True

            if is_task_arg:  # append task args
                tasks[-1] += f" {arg}"
                continue  # processed

            if arg.endswith(ARG_BEG):  # task name + explicit arg start
                arg = arg[: -len(ARG_BEG)]
                is_task_arg = True

            task_cmd = arg
            tasks.append(task_cmd)

        args.task = parse_composite(args.task, tasks)
        args.task.cwd = args.cwd
        args.task.env = args.env
        args.task.env_file = args.env_file

        if not args.help and not args.version and not args.task.depends:
            # default action
            args.list_ = True

        # all args processed
        return args

Class variables

var env : Dict[str, str]

Environment variable overrides.

var workspace : List[str]

List of workspace patterns to run tasks in.

var taskTask

A composite task for the tasks given on the command-line.

var help : bool

Whether to show the usage.

var version : bool

Whether to show the version.

var debug : bool

Whether to show debug messages

var dry_run : bool

Whether to skip actually running tasks.

var no_config : bool

Disable searching for config.

var no_project : bool

Disable searching for project dependencies (.venv, node_modules).

var list_ : bool

Whether to show available tasks

var cwd : Optional[pathlib.Path]

Path to run tasks in.

var env_file : Optional[pathlib.Path]

Path to environment variables.

var file : Optional[pathlib.Path]

Path to task definitions.

var pre : bool

EXPERIMENTAL: Whether to run pre- tasks.

var post : bool

EXPERIMENTAL: Whether to run post- tasks.

Static methods

def parse(argv: List[str]) ‑> Args

Parse command-line arguments in a docopt-like way.

Methods

def copy(self) ‑> Args

Return a copy of this object.

def as_argv(self) ‑> List[str]

Return args as a string.