{"record":{"id":"1dd4af5c6406b156","repo":"datawhalechina/hello-agents","slug":"metric-imperial","errorCode":null,"errorMessage":"单位必须是 'metric' 或 'imperial'","messagePattern":"单位必须是 'metric' 或 'imperial'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"Co-creation-projects/allen2000-FashionDailyDress/weather.py","lineNumber":136,"sourceCode":"        :return: 格式化后的天气信息字符串\n        \"\"\"\n        weather_data = self._parse_weather_data(data)\n        \n        return (\n            f\"🏙️ 城市: {weather_data['city']}\\n\"\n            f\"🌡️ 温度: {weather_data['temperature']}{weather_data['temperature_unit']}\\n\"\n            f\"📝 天气: {weather_data['description']}\\n\"\n            f\"💧 湿度: {weather_data['humidity']}%\\n\"\n            f\"🌬️ 风速: {weather_data['wind_speed']} {weather_data['wind_unit']}\"\n        )\n    \n    def set_unit(self, unit):\n        \"\"\"\n        设置温度单位\n        :param unit: 温度单位（metric=摄氏，imperial=华氏）\n        \"\"\"\n        if unit not in ['metric', 'imperial']:\n            raise ValueError(\"单位必须是 'metric' 或 'imperial'\")\n        self.unit = unit\n    \n    def set_api_key(self, api_key):\n        \"\"\"\n        设置API密钥\n        :param api_key: 新的API密钥\n        \"\"\"\n        self.api_key = api_key\n\n\ndef get_weather(city_name, api_key=os.environ.get(\"OPENWEATHER_API_KEY\"), unit='metric'):\n    \"\"\"\n    向后兼容的函数，使用Weather类实现\n    :param city_name: 城市名称（英文）\n    :param api_key: 你的OpenWeatherMap API密钥\n    :param unit: 温度单位（metric=摄氏，imperial=华氏）\n    :return: 格式化后的天气信息\n    \"\"\"","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/allen2000-FashionDailyDress/weather.py#L118-L154","documentation":"ValueError raised by WeatherClient.set_unit when the unit argument is not exactly 'metric' or 'imperial'. The unit is passed straight into the OpenWeather 'units' query parameter, and the API only accepts those two literals ('standard' would also be valid for OpenWeather but is deliberately excluded here). Case matters: 'Metric' or 'METRIC' raise.","triggerScenarios":"set_unit('c'), set_unit('C'), set_unit('celsius'), set_unit('standard'), set_unit('Metric') — all raise; user-config or LLM-provided unit strings not normalized before the call; uppercase values from an enum or CLI flag; passing the display symbol '°C'.","commonSituations":"Dress-recommendation agent letting a user say '摄氏' or 'C' and forwarding it raw; config file storing unit as 'Celsius'; CLI accepting --unit without validation.","solutions":["Normalize before validating: unit = unit.strip().lower() and map synonyms ('c','celsius','℃' -> 'metric'; 'f','fahrenheit','℉' -> 'imperial')","Use a Literal/Enum at the boundary so invalid values are rejected with a clear message earlier","If 'standard' (Kelvin) should be supported, add it to the allowed set and update the display logic at line 107 which currently assumes a metric/imperial binary"],"exampleFix":"# before\ndef set_unit(self, unit):\n    if unit not in ['metric', 'imperial']:\n        raise ValueError(\"单位必须是 'metric' 或 'imperial'\")\n    self.unit = unit\n\n# after\n_UNIT_ALIASES = {\n    'metric': 'metric', 'c': 'metric', 'celsius': 'metric', '℃': 'metric',\n    'imperial': 'imperial', 'f': 'imperial', 'fahrenheit': 'imperial', '℉': 'imperial',\n}\n\ndef set_unit(self, unit):\n    unit = _UNIT_ALIASES.get(str(unit).strip().lower())\n    if unit is None:\n        raise ValueError(\n            \"单位必须是 'metric' 或 'imperial'（接受别名 c/celsius/f/fahrenheit）\"\n        )\n    self.unit = unit","handlingStrategy":"validation","validationCode":"ALLOWED_UNITS = ('metric', 'imperial')\n\ndef normalize_unit(unit: str) -> str | None:\n    u = str(unit).strip().lower()\n    return u if u in ALLOWED_UNITS else None\n\nunit = normalize_unit(raw)\nif unit is None:\n    # reject / re-prompt before touching the client\n    ...","typeGuard":"from typing import Literal\n\nUnit = Literal['metric', 'imperial']\n\ndef is_unit(v) -> bool:\n    return v in ('metric', 'imperial')","tryCatchPattern":"try:\n    client.set_unit(raw_unit)\nexcept ValueError:\n    client.set_unit('metric')  # safe default\n    notify_user('unrecognized unit, using Celsius')","preventionTips":["Normalize case and map synonyms (c/celsius/f/fahrenheit) before calling set_unit","Type the boundary with Literal['metric','imperial'] or an Enum so invalid input is caught earlier","Validate any LLM- or user-supplied unit string before forwarding it to the weather client"],"tags":["openweather","validation","units","python","normalization"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}