Source code for reemote.utilities.generate_execution_results
# Copyright (c) 2025 Kim Jarvis TPF Software Services S.A. kim.jarvis@tpfsystems.com # This software is licensed under the MIT License. See the LICENSE file for details.#fromtabulateimporttabulatedef_generate_table(data):"""Transforms raw event data into a structured grid format. This internal helper function processes a list of event dictionaries, groups them by command, and pivots the data to create a table structure. For each unique host found in the data, it generates 'Executed' and 'Changed' columns. The primary purpose is to group consecutive entries that share the same command string into a single row, showing the execution status across all relevant hosts. Args: data (list[dict]): A list of dictionaries, where each dictionary represents a single event. Each dictionary must contain keys: 'host' (str), 'executed' (any), 'changed' (any), and 'op' (dict). The 'op' dictionary must contain a 'command' (str) key. Returns: tuple: A tuple containing two elements: - result (dict): A dictionary with 'columnDefs' and 'rowData', suitable for a grid component. - hosts (list[str]): A sorted list of unique hostnames found in the data. Raises: TypeError: If the input 'data' is not a list of dictionaries, preventing host extraction. """# Step 1: Extract unique hoststry:hosts=sorted(set(entry['host']forentryindata))exceptTypeErrorase:print("Error: The 'data' variable must be a list of dictionaries.")raisee# Step 2: Initialize columnDefs and rowDataresult={"columnDefs":[],"rowData":[]}# Add the 'Command' column to columnDefsresult["columnDefs"].append({"headerName":"Command","field":"command"})# Add two columns for each host: Executed and Changedforhostinhosts:result["columnDefs"].append({"headerName":f"{host} Executed","field":f"{host.replace(".","_")}_executed"})result["columnDefs"].append({"headerName":f"{host} Changed","field":f"{host.replace(".","_")}_changed"})# Step 3: Process data by grouping consecutive entries with the same commandi=0whilei<len(data):# Get the current commandcommand=data[i]['op']['command']# Create a new row for this commandrow={"command":command}# Initialize all host columns as emptyforhinhosts:row[f"{h}_executed"]=""row[f"{h}_changed"]=""# Process all consecutive entries with this same commandwhilei<len(data)anddata[i]['op']['command']==command:entry=data[i]host=entry['host']executed=entry['executed']changed=entry['changed']# Add the current host's datarow[f"{host.replace(".","_")}_executed"]=executedrow[f"{host.replace(".","_")}_changed"]=changedi+=1# Move to next entry# Add the completed row to rowDataresult["rowData"].append(row)returnresult,hosts
[docs]defgenerate_table(data):"""Generates a human-readable ASCII grid table from event data. This function takes a list of event data, processes it into a tabular format, and then uses the `tabulate` library to create a formatted string representation of the table. It is ideal for displaying command execution results in a console or log builtin. It internally uses `_generate_table` to structure the data before formatting. Args: data (list[dict]): A list of event dictionaries. See the docstring for `_generate_table` for the required structure. Returns: str: A string containing the formatted ASCII table in 'grid' format. """result,hosts=_generate_table(data)# Step 4: Convert to tabulate formatheaders=[col['headerName']forcolinresult["columnDefs"]]table_data=[]forrowinresult["rowData"]:formatted_row=[row['command']]# Start with commandforhostinhosts:executed=row[f"{host.replace(".","_")}_executed"]changed=row[f"{host.replace(".","_")}_changed"]formatted_row.append(executedifexecuted!=""else"")formatted_row.append(changedifchanged!=""else"")table_data.append(formatted_row)# Step 5: Return the tablereturntabulate(table_data,headers=headers,tablefmt="grid")
[docs]defgenerate_grid(data):"""Generates a human-readable ASCII grid table from event data. This function takes a list of event data, processes it into a tabular format, and then uses the `tabulate` library to create a formatted string representation of the table. It is ideal for displaying command execution results in a console or log builtin. It internally uses `_generate_table` to structure the data before formatting. Args: data (list[dict]): A list of event dictionaries. See the docstring for `_generate_table` for the required structure. Returns: str: A string containing the formatted ASCII table in 'grid' format. """result,hosts=_generate_table(data)returnresult["columnDefs"],result["rowData"],