Vangorra withings fix (#27404)

* Fixing connection issues with withings API by switching to a maintained client codebase.

* Updating requirements files.

* Adding withings api to requirements script.

* Using version of withings api with static version in setup.py.

* Updating requirements files.
pull/27572/head
Robert Van Gorkom 2019-10-10 11:22:36 -07:00 committed by Paulus Schoutsen
parent 7398e06c78
commit 863cf9823b
9 changed files with 127 additions and 117 deletions

View File

@ -4,7 +4,7 @@ import logging
import re
import time
import nokia
import withings_api as withings
from oauthlib.oauth2.rfc6749.errors import MissingTokenError
from requests_oauthlib import TokenUpdated
@ -68,7 +68,9 @@ class WithingsDataManager:
service_available = None
def __init__(self, hass: HomeAssistantType, profile: str, api: nokia.NokiaApi):
def __init__(
self, hass: HomeAssistantType, profile: str, api: withings.WithingsApi
):
"""Constructor."""
self._hass = hass
self._api = api
@ -253,7 +255,7 @@ def create_withings_data_manager(
"""Set up the sensor config entry."""
entry_creds = entry.data.get(const.CREDENTIALS) or {}
profile = entry.data[const.PROFILE]
credentials = nokia.NokiaCredentials(
credentials = withings.WithingsCredentials(
entry_creds.get("access_token"),
entry_creds.get("token_expiry"),
entry_creds.get("token_type"),
@ -266,7 +268,7 @@ def create_withings_data_manager(
def credentials_saver(credentials_param):
_LOGGER.debug("Saving updated credentials of type %s", type(credentials_param))
# Sanitizing the data as sometimes a NokiaCredentials object
# Sanitizing the data as sometimes a WithingsCredentials object
# is passed through from the API.
cred_data = credentials_param
if not isinstance(credentials_param, dict):
@ -275,8 +277,8 @@ def create_withings_data_manager(
entry.data[const.CREDENTIALS] = cred_data
hass.config_entries.async_update_entry(entry, data={**entry.data})
_LOGGER.debug("Creating nokia api instance")
api = nokia.NokiaApi(
_LOGGER.debug("Creating withings api instance")
api = withings.WithingsApi(
credentials, refresh_cb=(lambda token: credentials_saver(api.credentials))
)

View File

@ -4,7 +4,7 @@ import logging
from typing import Optional
import aiohttp
import nokia
import withings_api as withings
import voluptuous as vol
from homeassistant import config_entries, data_entry_flow
@ -75,7 +75,7 @@ class WithingsFlowHandler(config_entries.ConfigFlow):
profile,
)
return nokia.NokiaAuth(
return withings.WithingsAuth(
client_id,
client_secret,
callback_uri,

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/withings",
"requirements": [
"nokia==1.2.0"
"withings-api==2.0.0b8"
],
"dependencies": [
"api",

View File

@ -865,9 +865,6 @@ niko-home-control==0.2.1
# homeassistant.components.nilu
niluclient==0.1.2
# homeassistant.components.withings
nokia==1.2.0
# homeassistant.components.nederlandse_spoorwegen
nsapi==2.7.4
@ -1973,6 +1970,9 @@ websockets==6.0
# homeassistant.components.wirelesstag
wirelesstagpy==0.4.0
# homeassistant.components.withings
withings-api==2.0.0b8
# homeassistant.components.wunderlist
wunderpy2==0.1.6

View File

@ -228,9 +228,6 @@ minio==4.0.9
# homeassistant.components.ssdp
netdisco==2.6.0
# homeassistant.components.withings
nokia==1.2.0
# homeassistant.components.iqvia
# homeassistant.components.opencv
# homeassistant.components.tensorflow

View File

@ -1,7 +1,7 @@
"""Common data for for the withings component tests."""
import time
import nokia
import withings_api as withings
import homeassistant.components.withings.const as const
@ -92,7 +92,7 @@ def new_measure(type_str, value, unit):
}
def nokia_sleep_response(states):
def withings_sleep_response(states):
"""Create a sleep response based on states."""
data = []
for state in states:
@ -104,10 +104,10 @@ def nokia_sleep_response(states):
)
)
return nokia.NokiaSleep(new_sleep_data("aa", data))
return withings.WithingsSleep(new_sleep_data("aa", data))
NOKIA_MEASURES_RESPONSE = nokia.NokiaMeasures(
WITHINGS_MEASURES_RESPONSE = withings.WithingsMeasures(
{
"updatetime": "",
"timezone": "",
@ -174,7 +174,7 @@ NOKIA_MEASURES_RESPONSE = nokia.NokiaMeasures(
)
NOKIA_SLEEP_RESPONSE = nokia_sleep_response(
WITHINGS_SLEEP_RESPONSE = withings_sleep_response(
[
const.MEASURE_TYPE_SLEEP_STATE_AWAKE,
const.MEASURE_TYPE_SLEEP_STATE_LIGHT,
@ -183,7 +183,7 @@ NOKIA_SLEEP_RESPONSE = nokia_sleep_response(
]
)
NOKIA_SLEEP_SUMMARY_RESPONSE = nokia.NokiaSleepSummary(
WITHINGS_SLEEP_SUMMARY_RESPONSE = withings.WithingsSleepSummary(
{
"series": [
new_sleep_summary(

View File

@ -3,7 +3,7 @@ import time
from typing import Awaitable, Callable, List
import asynctest
import nokia
import withings_api as withings
import pytest
import homeassistant.components.api as api
@ -15,9 +15,9 @@ from homeassistant.const import CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_METRIC
from homeassistant.setup import async_setup_component
from .common import (
NOKIA_MEASURES_RESPONSE,
NOKIA_SLEEP_RESPONSE,
NOKIA_SLEEP_SUMMARY_RESPONSE,
WITHINGS_MEASURES_RESPONSE,
WITHINGS_SLEEP_RESPONSE,
WITHINGS_SLEEP_SUMMARY_RESPONSE,
)
@ -34,17 +34,17 @@ class WithingsFactoryConfig:
measures: List[str] = None,
unit_system: str = None,
throttle_interval: int = const.THROTTLE_INTERVAL,
nokia_request_response="DATA",
nokia_measures_response: nokia.NokiaMeasures = NOKIA_MEASURES_RESPONSE,
nokia_sleep_response: nokia.NokiaSleep = NOKIA_SLEEP_RESPONSE,
nokia_sleep_summary_response: nokia.NokiaSleepSummary = NOKIA_SLEEP_SUMMARY_RESPONSE,
withings_request_response="DATA",
withings_measures_response: withings.WithingsMeasures = WITHINGS_MEASURES_RESPONSE,
withings_sleep_response: withings.WithingsSleep = WITHINGS_SLEEP_RESPONSE,
withings_sleep_summary_response: withings.WithingsSleepSummary = WITHINGS_SLEEP_SUMMARY_RESPONSE,
) -> None:
"""Constructor."""
self._throttle_interval = throttle_interval
self._nokia_request_response = nokia_request_response
self._nokia_measures_response = nokia_measures_response
self._nokia_sleep_response = nokia_sleep_response
self._nokia_sleep_summary_response = nokia_sleep_summary_response
self._withings_request_response = withings_request_response
self._withings_measures_response = withings_measures_response
self._withings_sleep_response = withings_sleep_response
self._withings_sleep_summary_response = withings_sleep_summary_response
self._withings_config = {
const.CLIENT_ID: "my_client_id",
const.CLIENT_SECRET: "my_client_secret",
@ -103,24 +103,24 @@ class WithingsFactoryConfig:
return self._throttle_interval
@property
def nokia_request_response(self):
def withings_request_response(self):
"""Request response."""
return self._nokia_request_response
return self._withings_request_response
@property
def nokia_measures_response(self) -> nokia.NokiaMeasures:
def withings_measures_response(self) -> withings.WithingsMeasures:
"""Measures response."""
return self._nokia_measures_response
return self._withings_measures_response
@property
def nokia_sleep_response(self) -> nokia.NokiaSleep:
def withings_sleep_response(self) -> withings.WithingsSleep:
"""Sleep response."""
return self._nokia_sleep_response
return self._withings_sleep_response
@property
def nokia_sleep_summary_response(self) -> nokia.NokiaSleepSummary:
def withings_sleep_summary_response(self) -> withings.WithingsSleepSummary:
"""Sleep summary response."""
return self._nokia_sleep_summary_response
return self._withings_sleep_summary_response
class WithingsFactoryData:
@ -130,21 +130,21 @@ class WithingsFactoryData:
self,
hass,
flow_id,
nokia_auth_get_credentials_mock,
nokia_api_request_mock,
nokia_api_get_measures_mock,
nokia_api_get_sleep_mock,
nokia_api_get_sleep_summary_mock,
withings_auth_get_credentials_mock,
withings_api_request_mock,
withings_api_get_measures_mock,
withings_api_get_sleep_mock,
withings_api_get_sleep_summary_mock,
data_manager_get_throttle_interval_mock,
):
"""Constructor."""
self._hass = hass
self._flow_id = flow_id
self._nokia_auth_get_credentials_mock = nokia_auth_get_credentials_mock
self._nokia_api_request_mock = nokia_api_request_mock
self._nokia_api_get_measures_mock = nokia_api_get_measures_mock
self._nokia_api_get_sleep_mock = nokia_api_get_sleep_mock
self._nokia_api_get_sleep_summary_mock = nokia_api_get_sleep_summary_mock
self._withings_auth_get_credentials_mock = withings_auth_get_credentials_mock
self._withings_api_request_mock = withings_api_request_mock
self._withings_api_get_measures_mock = withings_api_get_measures_mock
self._withings_api_get_sleep_mock = withings_api_get_sleep_mock
self._withings_api_get_sleep_summary_mock = withings_api_get_sleep_summary_mock
self._data_manager_get_throttle_interval_mock = (
data_manager_get_throttle_interval_mock
)
@ -160,29 +160,29 @@ class WithingsFactoryData:
return self._flow_id
@property
def nokia_auth_get_credentials_mock(self):
def withings_auth_get_credentials_mock(self):
"""Get auth credentials mock."""
return self._nokia_auth_get_credentials_mock
return self._withings_auth_get_credentials_mock
@property
def nokia_api_request_mock(self):
def withings_api_request_mock(self):
"""Get request mock."""
return self._nokia_api_request_mock
return self._withings_api_request_mock
@property
def nokia_api_get_measures_mock(self):
def withings_api_get_measures_mock(self):
"""Get measures mock."""
return self._nokia_api_get_measures_mock
return self._withings_api_get_measures_mock
@property
def nokia_api_get_sleep_mock(self):
def withings_api_get_sleep_mock(self):
"""Get sleep mock."""
return self._nokia_api_get_sleep_mock
return self._withings_api_get_sleep_mock
@property
def nokia_api_get_sleep_summary_mock(self):
def withings_api_get_sleep_summary_mock(self):
"""Get sleep summary mock."""
return self._nokia_api_get_sleep_summary_mock
return self._withings_api_get_sleep_summary_mock
@property
def data_manager_get_throttle_interval_mock(self):
@ -243,9 +243,9 @@ def withings_factory_fixture(request, hass) -> WithingsFactory:
assert await async_setup_component(hass, http.DOMAIN, config.hass_config)
assert await async_setup_component(hass, api.DOMAIN, config.hass_config)
nokia_auth_get_credentials_patch = asynctest.patch(
"nokia.NokiaAuth.get_credentials",
return_value=nokia.NokiaCredentials(
withings_auth_get_credentials_patch = asynctest.patch(
"withings_api.WithingsAuth.get_credentials",
return_value=withings.WithingsCredentials(
access_token="my_access_token",
token_expiry=time.time() + 600,
token_type="my_token_type",
@ -255,28 +255,33 @@ def withings_factory_fixture(request, hass) -> WithingsFactory:
consumer_secret=config.withings_config.get(const.CLIENT_SECRET),
),
)
nokia_auth_get_credentials_mock = nokia_auth_get_credentials_patch.start()
withings_auth_get_credentials_mock = withings_auth_get_credentials_patch.start()
nokia_api_request_patch = asynctest.patch(
"nokia.NokiaApi.request", return_value=config.nokia_request_response
withings_api_request_patch = asynctest.patch(
"withings_api.WithingsApi.request",
return_value=config.withings_request_response,
)
nokia_api_request_mock = nokia_api_request_patch.start()
withings_api_request_mock = withings_api_request_patch.start()
nokia_api_get_measures_patch = asynctest.patch(
"nokia.NokiaApi.get_measures", return_value=config.nokia_measures_response
withings_api_get_measures_patch = asynctest.patch(
"withings_api.WithingsApi.get_measures",
return_value=config.withings_measures_response,
)
nokia_api_get_measures_mock = nokia_api_get_measures_patch.start()
withings_api_get_measures_mock = withings_api_get_measures_patch.start()
nokia_api_get_sleep_patch = asynctest.patch(
"nokia.NokiaApi.get_sleep", return_value=config.nokia_sleep_response
withings_api_get_sleep_patch = asynctest.patch(
"withings_api.WithingsApi.get_sleep",
return_value=config.withings_sleep_response,
)
nokia_api_get_sleep_mock = nokia_api_get_sleep_patch.start()
withings_api_get_sleep_mock = withings_api_get_sleep_patch.start()
nokia_api_get_sleep_summary_patch = asynctest.patch(
"nokia.NokiaApi.get_sleep_summary",
return_value=config.nokia_sleep_summary_response,
withings_api_get_sleep_summary_patch = asynctest.patch(
"withings_api.WithingsApi.get_sleep_summary",
return_value=config.withings_sleep_summary_response,
)
withings_api_get_sleep_summary_mock = (
withings_api_get_sleep_summary_patch.start()
)
nokia_api_get_sleep_summary_mock = nokia_api_get_sleep_summary_patch.start()
data_manager_get_throttle_interval_patch = asynctest.patch(
"homeassistant.components.withings.common.WithingsDataManager"
@ -295,11 +300,11 @@ def withings_factory_fixture(request, hass) -> WithingsFactory:
patches.extend(
[
nokia_auth_get_credentials_patch,
nokia_api_request_patch,
nokia_api_get_measures_patch,
nokia_api_get_sleep_patch,
nokia_api_get_sleep_summary_patch,
withings_auth_get_credentials_patch,
withings_api_request_patch,
withings_api_get_measures_patch,
withings_api_get_sleep_patch,
withings_api_get_sleep_summary_patch,
data_manager_get_throttle_interval_patch,
get_measures_patch,
]
@ -328,11 +333,11 @@ def withings_factory_fixture(request, hass) -> WithingsFactory:
return WithingsFactoryData(
hass,
flow_id,
nokia_auth_get_credentials_mock,
nokia_api_request_mock,
nokia_api_get_measures_mock,
nokia_api_get_sleep_mock,
nokia_api_get_sleep_summary_mock,
withings_auth_get_credentials_mock,
withings_api_request_mock,
withings_api_get_measures_mock,
withings_api_get_sleep_mock,
withings_api_get_sleep_summary_mock,
data_manager_get_throttle_interval_mock,
)

View File

@ -1,6 +1,6 @@
"""Tests for the Withings component."""
from asynctest import MagicMock
import nokia
import withings_api as withings
from oauthlib.oauth2.rfc6749.errors import MissingTokenError
import pytest
from requests_oauthlib import TokenUpdated
@ -13,19 +13,19 @@ from homeassistant.components.withings.common import (
from homeassistant.exceptions import PlatformNotReady
@pytest.fixture(name="nokia_api")
def nokia_api_fixture():
"""Provide nokia api."""
nokia_api = nokia.NokiaApi.__new__(nokia.NokiaApi)
nokia_api.get_measures = MagicMock()
nokia_api.get_sleep = MagicMock()
return nokia_api
@pytest.fixture(name="withings_api")
def withings_api_fixture():
"""Provide withings api."""
withings_api = withings.WithingsApi.__new__(withings.WithingsApi)
withings_api.get_measures = MagicMock()
withings_api.get_sleep = MagicMock()
return withings_api
@pytest.fixture(name="data_manager")
def data_manager_fixture(hass, nokia_api: nokia.NokiaApi):
def data_manager_fixture(hass, withings_api: withings.WithingsApi):
"""Provide data manager."""
return WithingsDataManager(hass, "My Profile", nokia_api)
return WithingsDataManager(hass, "My Profile", withings_api)
def test_print_service():

View File

@ -2,7 +2,12 @@
from unittest.mock import MagicMock, patch
import asynctest
from nokia import NokiaApi, NokiaMeasures, NokiaSleep, NokiaSleepSummary
from withings_api import (
WithingsApi,
WithingsMeasures,
WithingsSleep,
WithingsSleepSummary,
)
import pytest
from homeassistant.components.withings import DOMAIN
@ -15,7 +20,7 @@ from homeassistant.helpers.entity_component import async_update_entity
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.util import slugify
from .common import nokia_sleep_response
from .common import withings_sleep_response
from .conftest import WithingsFactory, WithingsFactoryConfig
@ -120,9 +125,9 @@ async def test_health_sensor_state_none(
data = await withings_factory(
WithingsFactoryConfig(
measures=measure,
nokia_measures_response=None,
nokia_sleep_response=None,
nokia_sleep_summary_response=None,
withings_measures_response=None,
withings_sleep_response=None,
withings_sleep_summary_response=None,
)
)
@ -153,9 +158,9 @@ async def test_health_sensor_state_empty(
data = await withings_factory(
WithingsFactoryConfig(
measures=measure,
nokia_measures_response=NokiaMeasures({"measuregrps": []}),
nokia_sleep_response=NokiaSleep({"series": []}),
nokia_sleep_summary_response=NokiaSleepSummary({"series": []}),
withings_measures_response=WithingsMeasures({"measuregrps": []}),
withings_sleep_response=WithingsSleep({"series": []}),
withings_sleep_summary_response=WithingsSleepSummary({"series": []}),
)
)
@ -201,7 +206,8 @@ async def test_sleep_state_throttled(
data = await withings_factory(
WithingsFactoryConfig(
measures=[measure], nokia_sleep_response=nokia_sleep_response(sleep_states)
measures=[measure],
withings_sleep_response=withings_sleep_response(sleep_states),
)
)
@ -257,16 +263,16 @@ async def test_async_setup_entry_credentials_saver(hass: HomeAssistantType):
"expires_in": "2",
}
original_nokia_api = NokiaApi
nokia_api_instance = None
original_withings_api = WithingsApi
withings_api_instance = None
def new_nokia_api(*args, **kwargs):
nonlocal nokia_api_instance
nokia_api_instance = original_nokia_api(*args, **kwargs)
nokia_api_instance.request = MagicMock()
return nokia_api_instance
def new_withings_api(*args, **kwargs):
nonlocal withings_api_instance
withings_api_instance = original_withings_api(*args, **kwargs)
withings_api_instance.request = MagicMock()
return withings_api_instance
nokia_api_patch = patch("nokia.NokiaApi", side_effect=new_nokia_api)
withings_api_patch = patch("withings_api.WithingsApi", side_effect=new_withings_api)
session_patch = patch("requests_oauthlib.OAuth2Session")
client_patch = patch("oauthlib.oauth2.WebApplicationClient")
update_entry_patch = patch.object(
@ -275,7 +281,7 @@ async def test_async_setup_entry_credentials_saver(hass: HomeAssistantType):
wraps=hass.config_entries.async_update_entry,
)
with session_patch, client_patch, nokia_api_patch, update_entry_patch:
with session_patch, client_patch, withings_api_patch, update_entry_patch:
async_add_entities = MagicMock()
hass.config_entries.async_update_entry = MagicMock()
config_entry = ConfigEntry(
@ -298,7 +304,7 @@ async def test_async_setup_entry_credentials_saver(hass: HomeAssistantType):
await async_setup_entry(hass, config_entry, async_add_entities)
nokia_api_instance.set_token(expected_creds)
withings_api_instance.set_token(expected_creds)
new_creds = config_entry.data[const.CREDENTIALS]
assert new_creds["access_token"] == "my_access_token2"