1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 08:26:41 +01:00

Bump pyloadapi to 2.0.0 (#164495)

This commit is contained in:
Manu
2026-03-02 11:47:13 +01:00
committed by GitHub
parent fe830337c9
commit 0d97bfbc59
10 changed files with 70 additions and 953 deletions

View File

@@ -90,7 +90,7 @@ async def validate_input(hass: HomeAssistant, user_input: dict[str, Any]) -> Non
password=user_input[CONF_PASSWORD],
)
await pyload.login()
await pyload.get_status()
class PyLoadConfigFlow(ConfigFlow, domain=DOMAIN):

View File

@@ -64,19 +64,12 @@ class PyLoadCoordinator(DataUpdateCoordinator[PyLoadData]):
**await self.pyload.get_status(),
free_space=await self.pyload.free_space(),
)
except InvalidAuth:
try:
await self.pyload.login()
except InvalidAuth as exc:
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="setup_authentication_exception",
translation_placeholders={CONF_USERNAME: self.pyload.username},
) from exc
_LOGGER.debug(
"Unable to retrieve data due to cookie expiration, retrying after 20 seconds"
)
return self.data
except InvalidAuth as e:
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="setup_authentication_exception",
translation_placeholders={CONF_USERNAME: self.pyload.username},
) from e
except CannotConnect as e:
raise UpdateFailed(
translation_domain=DOMAIN,
@@ -92,7 +85,6 @@ class PyLoadCoordinator(DataUpdateCoordinator[PyLoadData]):
"""Set up the coordinator."""
try:
await self.pyload.login()
self.version = await self.pyload.version()
except CannotConnect as e:
raise ConfigEntryNotReady(

View File

@@ -8,5 +8,5 @@
"iot_class": "local_polling",
"loggers": ["pyloadapi"],
"quality_scale": "platinum",
"requirements": ["PyLoadAPI==1.4.2"]
"requirements": ["PyLoadAPI==2.0.0"]
}

2
requirements_all.txt generated
View File

@@ -56,7 +56,7 @@ PyFlume==0.6.5
PyFronius==0.8.0
# homeassistant.components.pyload
PyLoadAPI==1.4.2
PyLoadAPI==2.0.0
# homeassistant.components.met_eireann
PyMetEireann==2024.11.0

View File

@@ -56,7 +56,7 @@ PyFlume==0.6.5
PyFronius==0.8.0
# homeassistant.components.pyload
PyLoadAPI==1.4.2
PyLoadAPI==2.0.0
# homeassistant.components.met_eireann
PyMetEireann==2024.11.0

View File

@@ -3,7 +3,7 @@
from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, patch
from pyloadapi.types import LoginResponse, StatusServerResponse
from pyloadapi.types import StatusServerResponse
import pytest
from homeassistant.components.pyload.const import DEFAULT_NAME, DOMAIN
@@ -76,18 +76,6 @@ def mock_pyloadapi() -> Generator[MagicMock]:
client = mock_client.return_value
client.username = "username"
client.api_url = "https://pyload.local:8000/"
client.login.return_value = LoginResponse(
{
"_permanent": True,
"authenticated": True,
"id": 2,
"name": "username",
"role": 0,
"perms": 0,
"template": "default",
"_flashes": [["message", "Logged in successfully"]],
}
)
client.get_status.return_value = StatusServerResponse(
{

View File

@@ -1,823 +1,4 @@
# serializer version: 1
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_active_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_active_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Active downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Active downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.ACTIVE: 'active'>,
'unique_id': 'XXXXXXXXXXXXXX_active',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_active_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Active downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_active_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_downloads_in_queue-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_downloads_in_queue',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Downloads in queue',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Downloads in queue',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.QUEUE: 'queue'>,
'unique_id': 'XXXXXXXXXXXXXX_queue',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_downloads_in_queue-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Downloads in queue',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_downloads_in_queue',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_free_space-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_free_space',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Free space',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.FREE_SPACE: 'free_space'>,
'unique_id': 'XXXXXXXXXXXXXX_free_space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_free_space-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'pyLoad Free space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_free_space',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_speed-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_speed',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Speed',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_RATE: 'data_rate'>,
'original_icon': None,
'original_name': 'Speed',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.SPEED: 'speed'>,
'unique_id': 'XXXXXXXXXXXXXX_speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_speed-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_rate',
'friendly_name': 'pyLoad Speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_speed',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_total_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_total_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Total downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Total downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.TOTAL: 'total'>,
'unique_id': 'XXXXXXXXXXXXXX_total',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[CannotConnect][sensor.pyload_total_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Total downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_total_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_active_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_active_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Active downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Active downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.ACTIVE: 'active'>,
'unique_id': 'XXXXXXXXXXXXXX_active',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_active_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Active downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_active_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_downloads_in_queue-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_downloads_in_queue',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Downloads in queue',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Downloads in queue',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.QUEUE: 'queue'>,
'unique_id': 'XXXXXXXXXXXXXX_queue',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_downloads_in_queue-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Downloads in queue',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_downloads_in_queue',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '6',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_free_space-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_free_space',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Free space',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.FREE_SPACE: 'free_space'>,
'unique_id': 'XXXXXXXXXXXXXX_free_space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_free_space-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'pyLoad Free space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_free_space',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '93.1322574606165',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_speed-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_speed',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Speed',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_RATE: 'data_rate'>,
'original_icon': None,
'original_name': 'Speed',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.SPEED: 'speed'>,
'unique_id': 'XXXXXXXXXXXXXX_speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_speed-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_rate',
'friendly_name': 'pyLoad Speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_speed',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '43.247704',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_total_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_total_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Total downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Total downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.TOTAL: 'total'>,
'unique_id': 'XXXXXXXXXXXXXX_total',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[InvalidAuth][sensor.pyload_total_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Total downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_total_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '37',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_active_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_active_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Active downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Active downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.ACTIVE: 'active'>,
'unique_id': 'XXXXXXXXXXXXXX_active',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_active_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Active downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_active_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_downloads_in_queue-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_downloads_in_queue',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Downloads in queue',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Downloads in queue',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.QUEUE: 'queue'>,
'unique_id': 'XXXXXXXXXXXXXX_queue',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_downloads_in_queue-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Downloads in queue',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_downloads_in_queue',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_free_space-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_free_space',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Free space',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Free space',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.FREE_SPACE: 'free_space'>,
'unique_id': 'XXXXXXXXXXXXXX_free_space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_free_space-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'pyLoad Free space',
'unit_of_measurement': <UnitOfInformation.GIBIBYTES: 'GiB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_free_space',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_speed-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_speed',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Speed',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_RATE: 'data_rate'>,
'original_icon': None,
'original_name': 'Speed',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.SPEED: 'speed'>,
'unique_id': 'XXXXXXXXXXXXXX_speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_speed-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_rate',
'friendly_name': 'pyLoad Speed',
'unit_of_measurement': <UnitOfDataRate.MEGABITS_PER_SECOND: 'Mbit/s'>,
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_speed',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_total_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.pyload_total_downloads',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Total downloads',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Total downloads',
'platform': 'pyload',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PyLoadSensorEntity.TOTAL: 'total'>,
'unique_id': 'XXXXXXXXXXXXXX_total',
'unit_of_measurement': 'downloads',
})
# ---
# name: test_sensor_update_exceptions[ParserError][sensor.pyload_total_downloads-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'pyLoad Total downloads',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'downloads',
}),
'context': <ANY>,
'entity_id': 'sensor.pyload_total_downloads',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_setup[sensor.pyload_active_downloads-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -65,7 +65,7 @@ async def test_form_errors(
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
mock_pyloadapi.login.side_effect = exception
mock_pyloadapi.get_status.side_effect = exception
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
@@ -75,7 +75,7 @@ async def test_form_errors(
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": expected_error}
mock_pyloadapi.login.side_effect = None
mock_pyloadapi.get_status.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
USER_INPUT,
@@ -159,7 +159,7 @@ async def test_reauth_errors(
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
mock_pyloadapi.login.side_effect = side_effect
mock_pyloadapi.get_status.side_effect = side_effect
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
REAUTH_INPUT,
@@ -168,7 +168,7 @@ async def test_reauth_errors(
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": error_text}
mock_pyloadapi.login.side_effect = None
mock_pyloadapi.get_status.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
REAUTH_INPUT,
@@ -231,7 +231,7 @@ async def test_reconfigure_errors(
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reconfigure"
mock_pyloadapi.login.side_effect = side_effect
mock_pyloadapi.get_status.side_effect = side_effect
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
USER_INPUT,
@@ -240,7 +240,7 @@ async def test_reconfigure_errors(
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": error_text}
mock_pyloadapi.login.side_effect = None
mock_pyloadapi.get_status.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
USER_INPUT,
@@ -261,7 +261,7 @@ async def test_hassio_discovery(
) -> None:
"""Test flow started from Supervisor discovery."""
mock_pyloadapi.login.side_effect = InvalidAuth
mock_pyloadapi.get_status.side_effect = InvalidAuth
result = await hass.config_entries.flow.async_init(
DOMAIN,
@@ -273,7 +273,7 @@ async def test_hassio_discovery(
assert result["step_id"] == "hassio_confirm"
assert result["errors"] is None
mock_pyloadapi.login.side_effect = None
mock_pyloadapi.get_status.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_USERNAME: "pyload", CONF_PASSWORD: "pyload"}
@@ -325,7 +325,7 @@ async def test_hassio_discovery_errors(
) -> None:
"""Test flow started from Supervisor discovery."""
mock_pyloadapi.login.side_effect = side_effect
mock_pyloadapi.get_status.side_effect = side_effect
result = await hass.config_entries.flow.async_init(
DOMAIN,
@@ -344,7 +344,7 @@ async def test_hassio_discovery_errors(
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": error_text}
mock_pyloadapi.login.side_effect = None
mock_pyloadapi.get_status.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {CONF_USERNAME: "pyload", CONF_PASSWORD: "pyload"}

View File

@@ -1,9 +1,7 @@
"""Test pyLoad init."""
from datetime import timedelta
from unittest.mock import MagicMock
from freezegun.api import FrozenDateTimeFactory
from pyloadapi.exceptions import CannotConnect, InvalidAuth, ParserError
import pytest
@@ -11,7 +9,7 @@ from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
from homeassistant.const import CONF_PATH, CONF_URL
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, async_fire_time_changed
from tests.common import MockConfigEntry
async def test_entry_setup_unload(
@@ -44,7 +42,7 @@ async def test_config_entry_setup_errors(
side_effect: Exception,
) -> None:
"""Test config entry not ready."""
mock_pyloadapi.login.side_effect = side_effect
mock_pyloadapi.version.side_effect = side_effect
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@@ -58,7 +56,7 @@ async def test_config_entry_setup_invalid_auth(
mock_pyloadapi: MagicMock,
) -> None:
"""Test config entry authentication."""
mock_pyloadapi.login.side_effect = InvalidAuth
mock_pyloadapi.version.side_effect = InvalidAuth
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@@ -72,25 +70,61 @@ async def test_coordinator_update_invalid_auth(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test coordinator authentication."""
mock_pyloadapi.get_status.side_effect = InvalidAuth
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
mock_pyloadapi.login.side_effect = InvalidAuth
mock_pyloadapi.get_status.side_effect = InvalidAuth
freezer.tick(timedelta(seconds=20))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.SETUP_ERROR
assert any(config_entry.async_get_active_flows(hass, {SOURCE_REAUTH}))
async def test_coordinator_setup_invalid_auth(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: MagicMock,
) -> None:
"""Test coordinator setup authentication."""
mock_pyloadapi.version.side_effect = InvalidAuth
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.SETUP_ERROR
assert any(config_entry.async_get_active_flows(hass, {SOURCE_REAUTH}))
@pytest.mark.parametrize(
("exception", "state"),
[
(CannotConnect, ConfigEntryState.SETUP_RETRY),
(InvalidAuth, ConfigEntryState.SETUP_ERROR),
(ParserError, ConfigEntryState.SETUP_RETRY),
],
)
async def test_coordinator_update_errors(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: MagicMock,
exception: Exception,
state: ConfigEntryState,
) -> None:
"""Test coordinator setup authentication."""
mock_pyloadapi.get_status.side_effect = exception
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is state
@pytest.mark.usefixtures("mock_pyloadapi")
async def test_migration(
hass: HomeAssistant,

View File

@@ -3,18 +3,15 @@
from collections.abc import Generator
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
from pyloadapi.exceptions import CannotConnect, InvalidAuth, ParserError
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.pyload.coordinator import SCAN_INTERVAL
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
from tests.common import MockConfigEntry, snapshot_platform
@pytest.fixture(autouse=True)
@@ -42,78 +39,3 @@ async def test_setup(
assert config_entry.state is ConfigEntryState.LOADED
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
@pytest.mark.parametrize(
"exception",
[CannotConnect, InvalidAuth, ParserError],
)
async def test_sensor_update_exceptions(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: AsyncMock,
exception: Exception,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test if pyLoad sensors go unavailable when exceptions occur (except ParserErrors)."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
mock_pyloadapi.get_status.side_effect = exception
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
async def test_sensor_invalid_auth(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: AsyncMock,
caplog: pytest.LogCaptureFixture,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test invalid auth during sensor update."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
mock_pyloadapi.get_status.side_effect = InvalidAuth
mock_pyloadapi.login.side_effect = InvalidAuth
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (
"Authentication failed for username, verify your login credentials"
in caplog.text
)
async def test_pyload_pre_0_5_0(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_pyloadapi: AsyncMock,
) -> None:
"""Test setup of the pyload sensor platform."""
mock_pyloadapi.get_status.return_value = {
"pause": False,
"active": 1,
"queue": 6,
"total": 37,
"speed": 5405963.0,
"download": True,
"reconnect": False,
}
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED