Skip to main content
Glama
utils.py4.43 kB
"""Utility helpers for Excel integrations.""" import csv import io import json from typing import Any, Iterable, List, Sequence def format_size(size_bytes: int) -> str: """Format bytes to a readable string.""" if size_bytes < 1024: return f"{size_bytes} B" if size_bytes < 1024 * 1024: return f"{size_bytes / 1024:.2f} KB" if size_bytes < 1024 * 1024 * 1024: return f"{size_bytes / (1024 * 1024):.2f} MB" return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB" def normalize_output_format(output_format: str) -> str: """Normalize output format string.""" fmt = (output_format or "array").strip().lower() if fmt not in {"markdown", "json", "csv", "array"}: return "array" return fmt def _coerce_cell(value: Any) -> str: """Convert a cell value to string for text outputs.""" if value is None: return "" return str(value) def _ensure_headers(headers: Sequence[Any], width: int) -> List[str]: """Ensure headers exist for markdown/csv outputs.""" if headers: return [_coerce_cell(h) for h in headers] width = max(1, width) return [f"Column {idx + 1}" for idx in range(width)] def format_read_result(result: dict, output_format: str) -> str: """Format read_excel style result into the requested representation.""" fmt = normalize_output_format(output_format) rows: List[List[Any]] = result.get("rows") or [] sheet = result.get("sheet") or "Sheet1" total_rows = result.get("total_rows") returned_rows = result.get("returned_rows", len(rows)) truncated = result.get("truncated", False) path = result.get("path") range_requested = result.get("range") if fmt == "json": return json.dumps(result, ensure_ascii=False, indent=2) if fmt == "array": # Return raw array format as JSON for easy cell-level manipulation array_result = { "path": path, "sheet": sheet, "rows": rows, "total_rows": total_rows, "returned_rows": returned_rows, "truncated": truncated, } if range_requested: array_result["range"] = range_requested return json.dumps(array_result, ensure_ascii=False, indent=2) if fmt == "csv": buffer = io.StringIO() writer = csv.writer(buffer) for row in rows: writer.writerow([_coerce_cell(cell) for cell in row]) return buffer.getvalue() # Markdown formatting if not rows: lines: List[str] = [f"## Sheet: {sheet}"] if path: lines.append(f"Path: {path}") if range_requested: lines.append(f"Range: {range_requested}") lines.append("") lines.append("*No data*") return "\n".join(lines) # Use first row as headers for display, or generate column numbers first_row_width = len(rows[0]) if rows else 0 if rows: # Use first row as table headers for markdown display table_headers = [_coerce_cell(cell) for cell in rows[0]] data_rows = rows[1:] else: table_headers = [f"Column {idx + 1}" for idx in range(first_row_width)] data_rows = rows lines: List[str] = [f"## Sheet: {sheet}"] if path: lines.append(f"Path: {path}") if range_requested: lines.append(f"Range: {range_requested}") lines.append("") # Header row lines.append("| " + " | ".join(table_headers) + " |") lines.append("|" + "|".join(["---"] * len(table_headers)) + "|") # Data rows for row in data_rows: normalized_row = [_coerce_cell(cell) for cell in row] # Pad rows that are shorter than headers if len(normalized_row) < len(table_headers): normalized_row.extend([""] * (len(table_headers) - len(normalized_row))) lines.append("| " + " | ".join(normalized_row) + " |") # Info line if total_rows is not None: info = f"Showing {returned_rows} of {total_rows} rows" if truncated: info += " (truncated)" lines.extend(["", f"**Info**: {info}"]) return "\n".join(lines) def clean_rows(rows: Iterable[Iterable[Any]]) -> List[List[Any]]: """Convert rows to a list of lists with None replaced by empty strings.""" cleaned: List[List[str]] = [] for row in rows: cleaned.append([_coerce_cell(cell) for cell in row]) return cleaned

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/answerlink/MCP-Workspace-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server