Fetch the weather forecast for all periods for a given location. This asynchronous function retrieves the weather forecast for the specified location using the Geocoding API to obtain geographic coordinates and the Weather.gov API to fetch the weather forecast. It converts the temperatu
(location: str, format: str)
| 168 | print(f"Error: {error}") |
| 169 | |
| 170 | async def fetch_weather(location: str, format: str) -> str: |
| 171 | """Fetch the weather forecast for all periods for a given location. |
| 172 | |
| 173 | This asynchronous function retrieves the weather forecast for the specified |
| 174 | location using the Geocoding API to obtain geographic coordinates and the |
| 175 | Weather.gov API to fetch the weather forecast. It converts the temperatures |
| 176 | of all forecast periods into the desired unit and returns the forecast data |
| 177 | as a JSON-formatted string. |
| 178 | |
| 179 | Args: |
| 180 | location (str): The name of the location for which to fetch the weather forecast. |
| 181 | This can be any location recognized by the Geocoding API (e.g., "New York City"). |
| 182 | format (str): The temperature unit for the output. Accepts 'fahrenheit' or 'celsius'. |
| 183 | |
| 184 | Returns: |
| 185 | str: The JSON-formatted string of all forecast periods with temperatures |
| 186 | converted to the specified unit. |
| 187 | |
| 188 | Raises: |
| 189 | Returns an error message string prefixed with "ERROR:" if any step fails, such as |
| 190 | missing API keys, network errors, or data extraction issues. |
| 191 | """ |
| 192 | # Retrieve the Geocoding API key from environment variables |
| 193 | GEOCODING_API_KEY = os.getenv("GEOCODING_API_KEY") |
| 194 | if not GEOCODING_API_KEY: |
| 195 | return "ERROR: Geocoding API key is not set." |
| 196 | |
| 197 | # Construct the URL for the Geocoding API request |
| 198 | location_api_url = f"https://geocode.maps.co/search?q={location}&api_key={GEOCODING_API_KEY}" |
| 199 | |
| 200 | # Create an HTTP client that automatically follows redirects |
| 201 | async with httpx.AsyncClient(follow_redirects=True) as client: |
| 202 | try: |
| 203 | # Step 1: Fetch location data |
| 204 | location_response = await client.get(location_api_url) |
| 205 | location_response.raise_for_status() |
| 206 | location_data = location_response.json() |
| 207 | except httpx.HTTPError as e: |
| 208 | return f"ERROR: Failed to fetch location data. {str(e)}" |
| 209 | |
| 210 | if not location_data: |
| 211 | return "ERROR: No location data found." |
| 212 | |
| 213 | try: |
| 214 | # Extract latitude and longitude from the location data |
| 215 | lat = location_data[0]['lat'] |
| 216 | lon = location_data[0]['lon'] |
| 217 | except (IndexError, KeyError): |
| 218 | return "ERROR: Unable to extract latitude and longitude." |
| 219 | |
| 220 | # Construct the URL for the Weather.gov API points endpoint |
| 221 | point_metadata_endpoint = f"https://api.weather.gov/points/{float(lat):.4f},{float(lon):.4f}" |
| 222 | |
| 223 | try: |
| 224 | # Step 2: Fetch point metadata |
| 225 | point_metadata_response = await client.get(point_metadata_endpoint) |
| 226 | point_metadata_response.raise_for_status() |
| 227 | point_metadata = point_metadata_response.json() |