"""Handler for updating Datawrapper charts.""" import json from datawrapper import get_chart from mcp.types import TextContent from ..utils import get_api_token, json_to_dataframe async def update_chart(arguments: dict) -> list[TextContent]: """Update an existing chart's data or configuration.""" api_token = get_api_token() chart_id = arguments["chart_id"] # Get chart using factory function - returns correct Pydantic class instance chart = get_chart(chart_id, access_token=api_token) # Update data if provided if "data" in arguments: df = json_to_dataframe(arguments["data"]) chart.data = df # Update config if provided if "chart_config" in arguments: # Directly set attributes on the chart instance # Pydantic will validate each assignment automatically due to validate_assignment=True try: # Build a mapping of aliases to field names alias_to_field = {} for field_name, field_info in chart.model_fields.items(): # Add the field name itself alias_to_field[field_name] = field_name # Add any aliases if field_info.alias: alias_to_field[field_info.alias] = field_name for key, value in arguments["chart_config"].items(): # Convert alias to field name if needed field_name = alias_to_field.get(key, key) setattr(chart, field_name, value) except Exception as e: return [ TextContent( type="text", text=f"Invalid chart configuration: {str(e)}\n\n" f"Use get_chart_schema to see the valid schema for this chart type. " f"Only high-level Pydantic fields are accepted.", ) ] # Update using Pydantic instance method chart.update(access_token=api_token) result = { "chart_id": chart.chart_id, "message": "Chart updated successfully!", "edit_url": chart.get_editor_url(), } return [TextContent(type="text", text=json.dumps(result, indent=2))]