Beispiel #1
0
async def test_custom_logger(aresponses, caplog):
    """Test that a custom logger is used when provided to the client."""
    caplog.set_level(logging.DEBUG)
    custom_logger = logging.getLogger("custom")

    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/current/pollen/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("allergens_current_response.json"),
            status=200,
            headers={"Content-Type": "application/json; charset=utf-8"},
        ),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session, logger=custom_logger)
        await client.allergens.current()
        assert any(
            record.name == "custom" and "Received data" in record.message
            for record in caplog.records
        )

    aresponses.assert_plan_strictly_followed()
Beispiel #2
0
async def async_setup_entry(hass, config_entry):
    """Set up IQVIA as config entry."""
    websession = aiohttp_client.async_get_clientsession(hass)

    try:
        iqvia = IQVIAData(
            Client(config_entry.data[CONF_ZIP_CODE], websession),
            config_entry.data.get(CONF_MONITORED_CONDITIONS, list(SENSORS)))
        await iqvia.async_update()
    except InvalidZipError:
        _LOGGER.error('Invalid ZIP code provided: %s',
                      config_entry.data[CONF_ZIP_CODE])
        return False

    hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = iqvia

    hass.async_create_task(
        hass.config_entries.async_forward_entry_setup(config_entry, 'sensor'))

    async def refresh(event_time):
        """Refresh IQVIA data."""
        _LOGGER.debug('Updating IQVIA data')
        await iqvia.async_update()
        async_dispatcher_send(hass, TOPIC_DATA_UPDATE)

    hass.data[DOMAIN][DATA_LISTENER][
        config_entry.entry_id] = async_track_time_interval(
            hass, refresh, DEFAULT_SCAN_INTERVAL)

    return True
Beispiel #3
0
async def main():
    """Run."""
    async with ClientSession() as session:
        try:
            client = Client("17015", session=session)
            print(f'Client instantiated for ZIP "{client.zip_code}"')

            print()
            print("Allergen Data:")
            print(await client.allergens.current())
            print(await client.allergens.extended())
            print(await client.allergens.historic())
            print(await client.allergens.outlook())

            print()
            print("Disease Data:")
            print(await client.disease.current())
            print(await client.disease.extended())
            print(await client.disease.historic())

            print()
            print("Asthma Data:")
            print(await client.asthma.current())
            print(await client.asthma.extended())
            print(await client.asthma.historic())
        except IQVIAError as err:
            print(err)
Beispiel #4
0
async def async_setup(hass, config):
    """Set up the IQVIA component."""
    hass.data[DOMAIN] = {}
    hass.data[DOMAIN][DATA_CLIENT] = {}
    hass.data[DOMAIN][DATA_LISTENER] = {}

    conf = config[DOMAIN]

    websession = aiohttp_client.async_get_clientsession(hass)

    try:
        iqvia = IQVIAData(Client(conf[CONF_ZIP_CODE], websession),
                          conf[CONF_MONITORED_CONDITIONS])
        await iqvia.async_update()
    except IQVIAError as err:
        _LOGGER.error('Unable to set up IQVIA: %s', err)
        return False

    hass.data[DOMAIN][DATA_CLIENT] = iqvia

    hass.async_create_task(
        async_load_platform(hass, 'sensor', DOMAIN, {}, config))

    async def refresh(event_time):
        """Refresh IQVIA data."""
        _LOGGER.debug('Updating IQVIA data')
        await iqvia.async_update()
        async_dispatcher_send(hass, TOPIC_DATA_UPDATE)

    hass.data[DOMAIN][DATA_LISTENER] = async_track_time_interval(
        hass, refresh, DEFAULT_SCAN_INTERVAL)

    return True
Beispiel #5
0
async def async_setup_entry(hass, config_entry):
    """Set up IQVIA as config entry."""
    websession = aiohttp_client.async_get_clientsession(hass)

    if not config_entry.unique_id:
        # If the config entry doesn't already have a unique ID, set one:
        hass.config_entries.async_update_entry(
            config_entry, **{"unique_id": config_entry.data[CONF_ZIP_CODE]}
        )

    iqvia = IQVIAData(hass, Client(config_entry.data[CONF_ZIP_CODE], websession))

    try:
        await iqvia.async_update()
    except InvalidZipError:
        _LOGGER.error("Invalid ZIP code provided: %s", config_entry.data[CONF_ZIP_CODE])
        return False

    hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = iqvia

    hass.async_create_task(
        hass.config_entries.async_forward_entry_setup(config_entry, "sensor")
    )

    return True
Beispiel #6
0
async def test_request_timeout():
    """Test a request timeout."""
    with patch(
        "aiohttp.ClientSession.request", side_effect=asyncio.exceptions.TimeoutError
    ), pytest.raises(RequestError):
        async with aiohttp.ClientSession() as session:
            client = Client(TEST_ZIP, session=session, request_retries=1)
            await client.allergens.outlook()
Beispiel #7
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up IQVIA as config entry."""
    hass.data.setdefault(DOMAIN, {})
    hass.data[DOMAIN][entry.entry_id] = {}

    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)

    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()

    hass.data[DOMAIN][entry.entry_id] = coordinators
    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    return True
Beispiel #8
0
async def test_current_no_explicit_session(aresponses):
    """Test getting current allergen data without an explicit aiohttp ClientSession."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/current/pollen/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("allergens_current_response.json"), status=200),
    )

    client = Client(TEST_ZIP)
    current = await client.allergens.current()
    assert len(current["Location"]["periods"]) == 3
Beispiel #9
0
async def test_extended(aresponses):
    """Test getting extended asthma info."""
    aresponses.add(
        "www.asthmaforecast.com",
        f"/api/forecast/extended/asthma/{TEST_ZIP}",
        "get",
        aresponses.Response(text=load_fixture("asthma_extended_response.json"),
                            status=200),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        extended = await client.asthma.extended()
        assert len(extended["Location"]["periods"]) == 5
Beispiel #10
0
async def test_extended(aresponses):
    """Test getting extended cold and flu data."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/extended/cold/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("disease_extended_response.json"), status=200),
    )

    async with aiohttp.ClientSession() as websession:
        client = Client(TEST_ZIP, websession)
        extended = await client.disease.extended()
        assert len(extended["Location"]["periods"]) == 4
Beispiel #11
0
async def test_endpoints(aresponses):
    """Test getting historic asthma info."""
    aresponses.add(
        "www.asthmaforecast.com",
        f"/api/forecast/historic/asthma/{TEST_ZIP}",
        "get",
        aresponses.Response(text=load_fixture("asthma_historic_response.json"),
                            status=200),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        historic = await client.asthma.historic()
        assert len(historic["Location"]["periods"]) == 30
Beispiel #12
0
async def test_outlook(aresponses):
    """Test getting outlook allergen info."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/outlook/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("allergens_outlook_response.json"), status=200),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        outlook = await client.allergens.outlook()
        assert outlook["Trend"] == "subsiding"
async def test_historic(aresponses):
    """Test getting historic allergen info."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/historic/pollen/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("allergens_historic_response.json"), status=200),
    )

    async with aiohttp.ClientSession() as websession:
        client = Client(TEST_ZIP, websession)
        historic = await client.allergens.historic()
        assert len(historic["Location"]["periods"]) == 30
Beispiel #14
0
async def test_historic(aresponses):
    """Test getting historic cold and flu data."""
    aresponses.add(
        "www.flustar.com",
        f"/api/forecast/historic/cold/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("disease_historic_response.json"), status=200),
    )

    async with aiohttp.ClientSession() as websession:
        client = Client(TEST_ZIP, websession)
        historic = await client.disease.historic()
        assert len(historic["Location"]["periods"]) == 26
Beispiel #15
0
async def test_current(aresponses):
    """Test getting current asthma."""
    aresponses.add(
        "www.asthmaforecast.com",
        f"/api/forecast/current/asthma/{TEST_ZIP}",
        "get",
        aresponses.Response(text=load_fixture("asthma_current_response.json"),
                            status=200),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        current = await client.asthma.current()
        assert len(current["Location"]["periods"]) == 3
Beispiel #16
0
async def test_current(aresponses):
    """Test getting current cold and flu data."""
    aresponses.add(
        "flustar.com",
        f"/api/forecast/current/cold/{TEST_ZIP}",
        "get",
        aresponses.Response(text=load_fixture("disease_current_response.json"),
                            status=200),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        current = await client.disease.current()
        assert len(current["Location"]["periods"]) == 2
Beispiel #17
0
async def async_setup_entry(hass, entry):
    """Set up IQVIA as config entry."""
    hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = {}

    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], websession)

    async def async_get_data_from_api(api_coro):
        """Get data from a particular API coroutine."""
        try:
            return await api_coro()
        except IQVIAError as err:
            raise UpdateFailed from err

    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 = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][
            sensor_type
        ] = DataUpdateCoordinator(
            hass,
            LOGGER,
            name=f"{entry.data[CONF_ZIP_CODE]} {sensor_type}",
            update_interval=DEFAULT_SCAN_INTERVAL,
            update_method=lambda coro=api_coro: async_get_data_from_api(coro),
        )
        init_data_update_tasks.append(coordinator.async_refresh())

    await asyncio.gather(*init_data_update_tasks)

    for component in PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, component)
        )

    return True
Beispiel #18
0
async def test_http_error(aresponses):
    """Test an HTTP error."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/outlook/{TEST_ZIP}",
        "get",
        aresponses.Response(text="", status=500),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession() as session:
            client = Client(TEST_ZIP, session=session, request_retries=1)
            await client.allergens.outlook()

    aresponses.assert_plan_strictly_followed()
Beispiel #19
0
    async def async_step_user(self, user_input=None):
        """Handle the start of the config flow."""
        if not user_input:
            return await self._show_form()

        if user_input[CONF_ZIP_CODE] in configured_instances(self.hass):
            return await self._show_form({CONF_ZIP_CODE: "identifier_exists"})

        websession = aiohttp_client.async_get_clientsession(self.hass)

        try:
            Client(user_input[CONF_ZIP_CODE], websession)
        except InvalidZipError:
            return await self._show_form({CONF_ZIP_CODE: "invalid_zip_code"})

        return self.async_create_entry(title=user_input[CONF_ZIP_CODE], data=user_input)
Beispiel #20
0
async def test_historic(aresponses):
    """Test getting historic cold and flu data."""
    aresponses.add(
        "flustar.com",
        f"/api/forecast/historic/cold/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("disease_historic_response.json"),
            status=200,
            headers={"Content-Type": "application/json; charset=utf-8"},
        ),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        historic = await client.disease.historic()
        assert len(historic["Location"]["periods"]) == 26
Beispiel #21
0
    async def pollen(self, ctx, zip_code: str):
        """3 day pollen index.

        Pulls a 3 day pollen index with allergen information from `pollen.com`
        using the `pyiqvia` wrapper.

        Parameters:
            zip_code (str): Converted to string for convenience with piqvia.
        Returns:
            message (class Embed): The pollen index and allergen information
                                (allergen name, genus, and plant type) for the day.
        """
        client = Client(zip_code)
        data = await client.allergens.current()
        allergens = WeatherCog._format_pollen_data(data)

        await ctx.send(embed=allergens)
Beispiel #22
0
async def test_extended(aresponses):
    """Test getting extended allergen info."""
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/extended/pollen/{TEST_ZIP}",
        "get",
        aresponses.Response(
            text=load_fixture("allergens_extended_response.json"),
            status=200,
            headers={"Content-Type": "application/json; charset=utf-8"},
        ),
    )

    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        extended = await client.allergens.extended()
        assert len(extended["Location"]["periods"]) == 5
Beispiel #23
0
    async def async_step_user(self, user_input=None):
        """Handle the start of the config flow."""
        if not user_input:
            return self.async_show_form(step_id="user", data_schema=self.data_schema)

        await self.async_set_unique_id(user_input[CONF_ZIP_CODE])
        self._abort_if_unique_id_configured()

        websession = aiohttp_client.async_get_clientsession(self.opp)

        try:
            Client(user_input[CONF_ZIP_CODE], session=websession)
        except InvalidZipError:
            return self.async_show_form(
                step_id="user",
                data_schema=self.data_schema,
                errors={CONF_ZIP_CODE: "invalid_zip_code"},
            )

        return self.async_create_entry(title=user_input[CONF_ZIP_CODE], data=user_input)
Beispiel #24
0
async def test_request_error(aresponses):
    """Test authenticating the device."""
    aresponses.add(
        "www.pollen.com",
        f"/api/bad_endpoint/{TEST_ZIP}",
        "get",
        aresponses.Response(text="", status=404),
    )
    aresponses.add(
        "www.pollen.com",
        f"/api/forecast/outlook/{TEST_ZIP}",
        "get",
        aresponses.Response(text="", status=500),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession() as session:
            client = Client(TEST_ZIP, session=session)
            await client._request("get",
                                  "https://www.pollen.com/api/bad_endpoint")
            await client.allergens.outlook()
Beispiel #25
0
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()
Beispiel #26
0
async def test_bad_zip():
    """Test attempting to create a client with a bad ZIP code."""
    with pytest.raises(InvalidZipError):
        async with aiohttp.ClientSession() as session:
            _ = Client(TEST_BAD_ZIP, session=session)
Beispiel #27
0
async def test_create():
    """Test the creation of a client."""
    async with aiohttp.ClientSession() as session:
        client = Client(TEST_ZIP, session=session)
        assert client.zip_code == TEST_ZIP