migrated all pawprint work
This commit is contained in:
0
artery/veins/google/models/__init__.py
Normal file
0
artery/veins/google/models/__init__.py
Normal file
71
artery/veins/google/models/formatter.py
Normal file
71
artery/veins/google/models/formatter.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
Text formatters for spreadsheet data (LLM-friendly output).
|
||||
"""
|
||||
|
||||
from .spreadsheet import SpreadsheetMetadata, SheetValues
|
||||
|
||||
|
||||
def format_spreadsheet_metadata(metadata: SpreadsheetMetadata) -> str:
|
||||
"""Format spreadsheet metadata as text."""
|
||||
lines = [
|
||||
f"Spreadsheet: {metadata.title}",
|
||||
f"ID: {metadata.spreadsheet_id}",
|
||||
f"Locale: {metadata.locale or 'N/A'}",
|
||||
f"Timezone: {metadata.timezone or 'N/A'}",
|
||||
"",
|
||||
"Sheets:",
|
||||
]
|
||||
|
||||
for sheet in metadata.sheets:
|
||||
lines.append(
|
||||
f" [{sheet.index}] {sheet.title} "
|
||||
f"({sheet.row_count} rows x {sheet.column_count} cols)"
|
||||
)
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def format_sheet_values(values: SheetValues, max_rows: int = 100) -> str:
|
||||
"""
|
||||
Format sheet values as text table.
|
||||
|
||||
Args:
|
||||
values: Sheet values
|
||||
max_rows: Maximum rows to display
|
||||
"""
|
||||
lines = [
|
||||
f"Spreadsheet ID: {values.spreadsheet_id}",
|
||||
f"Range: {values.range}",
|
||||
f"Size: {values.row_count} rows x {values.column_count} cols",
|
||||
"",
|
||||
]
|
||||
|
||||
if not values.values:
|
||||
lines.append("(empty)")
|
||||
return "\n".join(lines)
|
||||
|
||||
# Display up to max_rows
|
||||
display_rows = values.values[:max_rows]
|
||||
|
||||
# Calculate column widths (for basic alignment)
|
||||
col_widths = [0] * values.column_count
|
||||
for row in display_rows:
|
||||
for i, cell in enumerate(row):
|
||||
col_widths[i] = max(col_widths[i], len(str(cell)))
|
||||
|
||||
# Format rows
|
||||
for row_idx, row in enumerate(display_rows):
|
||||
cells = []
|
||||
for col_idx, cell in enumerate(row):
|
||||
width = col_widths[col_idx] if col_idx < len(col_widths) else 0
|
||||
cells.append(str(cell).ljust(width))
|
||||
# Pad with empty cells if row is shorter
|
||||
while len(cells) < values.column_count:
|
||||
width = col_widths[len(cells)] if len(cells) < len(col_widths) else 0
|
||||
cells.append("".ljust(width))
|
||||
lines.append(" | ".join(cells))
|
||||
|
||||
if values.row_count > max_rows:
|
||||
lines.append(f"\n... ({values.row_count - max_rows} more rows)")
|
||||
|
||||
return "\n".join(lines)
|
||||
69
artery/veins/google/models/spreadsheet.py
Normal file
69
artery/veins/google/models/spreadsheet.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Spreadsheet models with self-parsing from Google Sheets API responses.
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional, List
|
||||
|
||||
|
||||
class SheetInfo(BaseModel):
|
||||
"""Individual sheet within a spreadsheet."""
|
||||
title: str
|
||||
sheet_id: int
|
||||
index: int
|
||||
row_count: int
|
||||
column_count: int
|
||||
|
||||
|
||||
class SpreadsheetMetadata(BaseModel):
|
||||
"""Spreadsheet metadata."""
|
||||
spreadsheet_id: str
|
||||
title: str
|
||||
locale: Optional[str] = None
|
||||
timezone: Optional[str] = None
|
||||
sheets: List[SheetInfo] = []
|
||||
|
||||
@classmethod
|
||||
def from_google(cls, data: dict) -> "SpreadsheetMetadata":
|
||||
"""Parse from Google Sheets API response."""
|
||||
sheets = [
|
||||
SheetInfo(
|
||||
title=sheet["properties"]["title"],
|
||||
sheet_id=sheet["properties"]["sheetId"],
|
||||
index=sheet["properties"]["index"],
|
||||
row_count=sheet["properties"]["gridProperties"].get("rowCount", 0),
|
||||
column_count=sheet["properties"]["gridProperties"].get("columnCount", 0),
|
||||
)
|
||||
for sheet in data.get("sheets", [])
|
||||
]
|
||||
|
||||
return cls(
|
||||
spreadsheet_id=data["spreadsheetId"],
|
||||
title=data["properties"]["title"],
|
||||
locale=data["properties"].get("locale"),
|
||||
timezone=data["properties"].get("timeZone"),
|
||||
sheets=sheets,
|
||||
)
|
||||
|
||||
|
||||
class SheetValues(BaseModel):
|
||||
"""Sheet data values."""
|
||||
spreadsheet_id: str
|
||||
range: str
|
||||
values: List[List[str]] # rows of cells
|
||||
row_count: int
|
||||
column_count: int
|
||||
|
||||
@classmethod
|
||||
def from_google(cls, spreadsheet_id: str, range_name: str, values: List[List]) -> "SheetValues":
|
||||
"""Parse from Google Sheets API values response."""
|
||||
row_count = len(values)
|
||||
column_count = max((len(row) for row in values), default=0)
|
||||
|
||||
return cls(
|
||||
spreadsheet_id=spreadsheet_id,
|
||||
range=range_name,
|
||||
values=values,
|
||||
row_count=row_count,
|
||||
column_count=column_count,
|
||||
)
|
||||
Reference in New Issue
Block a user