Source code for clickyaml.commander

from dataclasses import dataclass, field
from subprocess import Popen
from typing import Any
from typing import Callable
import click


[docs]@dataclass() class Commander: """Commander class takes in a parsed yaml and creates commands out of it. The *parsed_yaml* needs to be a dictionary of commands, and the *name* parameter is used to fetch the required information for the command. """ name: str #: Name of the command to create. It's value is used to fetch the parameters out of the parsed yaml and is also used to create a command of the same *name* parsed_yaml: dict #: Dictionary of commands, can include one or more commands. script: str = field(init=False, default="") #: Script associated with the command. _callback: Any = field(repr=False, default=None, init=False) _command: click.Command = field(init=False, repr=False) def __post_init__(self) -> None: self.script = self.parsed_yaml.get("script", "") self._callback = ( self.__default_callback__ if not self._callback else self._callback ) self.command_args = { key: self.parsed_yaml[key] for key in self.parsed_yaml.keys() - ["script"] } self._command = click.Command( name=self.name, callback=self._callback, **self.command_args ) def __default_callback__(self, **kwargs) -> None: """The default callback assigned to the click command.""" script_parms = self.script.split() params_in_order = [ kwargs[value.human_readable_name.lower()] for value in self.parsed_yaml["params"] ] Popen(script_parms + params_in_order, text=True) @property def command(self): """The click Command created out of the yaml. Uses the default callback or the callback assigned to the commander object. :return: Click command created from the yaml file. :rtype: class: click.Command """ self._command = click.Command( name=self.name, callback=self._callback, **self.command_args ) return self._command @property def callback(self): """ .. _callback: Callback to be linked to the click Command. If no callback is passed, the command is passed a default callback. The default callback runs the script associated with the command and passes the arguments in the order they are defined in the yaml file. :return: The callback linked to the click command :rtype: Callable """ return self._callback @callback.setter def callback(self, value): if callable(value): self._callback = value self.command.callback = value else: raise TypeError("'value' needs to be a function/lambda")