Source code for runly.commands

"""
Commands and command sets for RunLy.
"""

from dataclasses import dataclass, field
from typing import Dict, List, Optional, Set


[docs] @dataclass class Command: """Represents a command in a justfile.""" name: str script: str args: List[str] = field(default_factory=list) description: str = "" dependencies: Set[str] = field(default_factory=set)
[docs] def __post_init__(self): """Validate command after initialization.""" if not self.name: raise ValueError("Command name cannot be empty") if not isinstance(self.dependencies, set): self.dependencies = set(self.dependencies)
[docs] @dataclass class CommandSet: """A set of commands parsed from a justfile.""" commands: List[Command] variables: Dict[str, str] = field(default_factory=dict) default_command: Optional[str] = None
[docs] def __post_init__(self): """Validate command set after initialization.""" # Check for duplicate command names command_names = [cmd.name for cmd in self.commands] if len(command_names) != len(set(command_names)): dupes = [name for name in command_names if command_names.count(name) > 1] raise ValueError(f"Duplicate command names found: {', '.join(set(dupes))}") # Check if default command exists if self.default_command and self.default_command not in command_names: raise ValueError(f"Default command '{self.default_command}' not found")
[docs] def get_command(self, name: str) -> Optional[Command]: """Get a command by name.""" for cmd in self.commands: if cmd.name == name: return cmd return None
[docs] def get_commands_with_dependencies(self) -> Dict[str, Set[str]]: """Get a dictionary mapping command names to their dependencies.""" return {cmd.name: cmd.dependencies for cmd in self.commands}