async def test_request_retries(aresponses): """Test the request retry logic.""" aresponses.add( "www.pollen.com", f"/api/forecast/outlook/{TEST_ZIP}", "get", aresponses.Response(text="", status=500), ) aresponses.add( "www.pollen.com", f"/api/forecast/outlook/{TEST_ZIP}", "get", aresponses.Response(text="", status=500), ) aresponses.add( "www.pollen.com", f"/api/forecast/outlook/{TEST_ZIP}", "get", aresponses.Response( text=load_fixture("allergens_outlook_response.json"), status=200, headers={"Content-Type": "application/json; charset=utf-8"}, ), ) async with aiohttp.ClientSession() as session: client = Client(TEST_ZIP, session=session) client.disable_request_retries() with pytest.raises(RequestError): await client.allergens.outlook() client.enable_request_retries() await client.allergens.outlook() aresponses.assert_plan_strictly_followed()
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up IQVIA as config entry.""" if not entry.unique_id: # If the config entry doesn't already have a unique ID, set one: hass.config_entries.async_update_entry( entry, **{"unique_id": entry.data[CONF_ZIP_CODE]} ) websession = aiohttp_client.async_get_clientsession(hass) client = Client(entry.data[CONF_ZIP_CODE], session=websession) # We disable the client's request retry abilities here to avoid a lengthy (and # blocking) startup: client.disable_request_retries() async def async_get_data_from_api( api_coro: Callable[..., Awaitable] ) -> dict[str, Any]: """Get data from a particular API coroutine.""" try: data = await api_coro() except IQVIAError as err: raise UpdateFailed from err return cast(Dict[str, Any], data) coordinators = {} init_data_update_tasks = [] for sensor_type, api_coro in ( (TYPE_ALLERGY_FORECAST, client.allergens.extended), (TYPE_ALLERGY_INDEX, client.allergens.current), (TYPE_ALLERGY_OUTLOOK, client.allergens.outlook), (TYPE_ASTHMA_FORECAST, client.asthma.extended), (TYPE_ASTHMA_INDEX, client.asthma.current), (TYPE_DISEASE_FORECAST, client.disease.extended), (TYPE_DISEASE_INDEX, client.disease.current), ): coordinator = coordinators[sensor_type] = DataUpdateCoordinator( hass, LOGGER, name=f"{entry.data[CONF_ZIP_CODE]} {sensor_type}", update_interval=DEFAULT_SCAN_INTERVAL, update_method=partial(async_get_data_from_api, api_coro), ) init_data_update_tasks.append(coordinator.async_refresh()) results = await asyncio.gather(*init_data_update_tasks, return_exceptions=True) if all(isinstance(result, Exception) for result in results): # The IQVIA API can be selectively flaky, meaning that any number of the setup # API calls could fail. We only retry integration setup if *all* of the initial # API calls fail: raise ConfigEntryNotReady() # Once we've successfully authenticated, we re-enable client request retries: client.enable_request_retries() hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = coordinators hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True