from datetime import datetime import subprocess import xml.etree.ElementTree as ET from typing import Optional from .entry import Entry class RepeatEntry(Entry): """ Entry type for scripts that are executed on every update. """ def __init__(self, script: str, id: str, timestamp: datetime): """ Initialize a new repeat entry. Args: script: The script/command to execute id: Unique identifier for this entry timestamp: Creation timestamp for this entry """ super().__init__(id, timestamp) self._script = script self._stdout = "" self._stderr = "" self._exit_code: Optional[int] = None @property def script(self) -> str: """Get the script/command being executed.""" return self._script @property def stdout(self) -> str: """Get the captured standard output.""" return self._stdout @property def stderr(self) -> str: """Get the captured standard error.""" return self._stderr @property def exit_code(self) -> Optional[int]: """Get the exit code of the process (None if still running).""" return self._exit_code def update(self) -> None: """ Execute the script and update the output. Captures stdout, stderr and exit code from each execution. """ process = subprocess.run( self._script, shell=True, capture_output=True, text=True ) self._stdout = process.stdout self._stderr = process.stderr self._exit_code = process.returncode def generate_context(self) -> ET.Element: """ Generate an XML Element representing this repeat entry. Returns: ET.Element: XML element containing the entry's data """ element = ET.Element("repeat", { "id": self.id, "exit_code": str(self._exit_code) if self._exit_code is not None else "-1" }) element.text = self.script stdout_elem = ET.SubElement(element, "stdout") stdout_elem.text = self._stdout stderr_elem = ET.SubElement(element, "stderr") stderr_elem.text = self._stderr return element