diff --git a/.strict-typing b/.strict-typing index aa9c801fbf679..1bc3308f533cc 100644 --- a/.strict-typing +++ b/.strict-typing @@ -49,6 +49,7 @@ homeassistant.components.aftership.* homeassistant.components.air_quality.* homeassistant.components.airly.* homeassistant.components.airnow.* +homeassistant.components.airthings_ble.* homeassistant.components.airvisual.* homeassistant.components.airvisual_pro.* homeassistant.components.airzone.* diff --git a/homeassistant/components/airthings_ble/__init__.py b/homeassistant/components/airthings_ble/__init__.py index d7e6bddbcd4e1..1d62442f14de1 100644 --- a/homeassistant/components/airthings_ble/__init__.py +++ b/homeassistant/components/airthings_ble/__init__.py @@ -4,7 +4,8 @@ from datetime import timedelta import logging -from airthings_ble import AirthingsBluetoothDeviceData +from airthings_ble import AirthingsBluetoothDeviceData, AirthingsDevice +from bleak_retry_connector import close_stale_connections_by_address from homeassistant.components import bluetooth from homeassistant.config_entries import ConfigEntry @@ -30,6 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: is_metric = hass.config.units is METRIC_SYSTEM assert address is not None + await close_stale_connections_by_address(address) + ble_device = bluetooth.async_ble_device_from_address(hass, address) if not ble_device: @@ -37,13 +40,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: f"Could not find Airthings device with address {address}" ) - async def _async_update_method(): + async def _async_update_method() -> AirthingsDevice: """Get data from Airthings BLE.""" ble_device = bluetooth.async_ble_device_from_address(hass, address) airthings = AirthingsBluetoothDeviceData(_LOGGER, elevation, is_metric) try: - data = await airthings.update_device(ble_device) + data = await airthings.update_device(ble_device) # type: ignore[arg-type] except Exception as err: raise UpdateFailed(f"Unable to fetch data: {err}") from err diff --git a/homeassistant/components/alarm_control_panel/__init__.py b/homeassistant/components/alarm_control_panel/__init__.py index 9c53f2b7fd0b2..45e1d63e0c2d1 100644 --- a/homeassistant/components/alarm_control_panel/__init__.py +++ b/homeassistant/components/alarm_control_panel/__init__.py @@ -24,6 +24,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.config_validation import make_entity_service_schema from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -52,12 +53,6 @@ else: from homeassistant.backports.functools import cached_property -# As we import constants of the cost module here, we need to add the following -# functions to check for deprecated constants again -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - _LOGGER: Final = logging.getLogger(__name__) SCAN_INTERVAL: Final = timedelta(seconds=30) @@ -249,3 +244,13 @@ def state_attributes(self) -> dict[str, Any] | None: ATTR_CHANGED_BY: self.changed_by, ATTR_CODE_ARM_REQUIRED: self.code_arm_required, } + + +# As we import constants of the const module here, we need to add the following +# functions to check for deprecated constants again +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/alarm_control_panel/const.py b/homeassistant/components/alarm_control_panel/const.py index 90bbcba1314b5..fe4be649e195f 100644 --- a/homeassistant/components/alarm_control_panel/const.py +++ b/homeassistant/components/alarm_control_panel/const.py @@ -5,6 +5,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -60,10 +61,6 @@ class AlarmControlPanelEntityFeature(IntFlag): AlarmControlPanelEntityFeature.ARM_VACATION, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - CONDITION_TRIGGERED: Final = "is_triggered" CONDITION_DISARMED: Final = "is_disarmed" CONDITION_ARMED_HOME: Final = "is_armed_home" @@ -71,3 +68,10 @@ class AlarmControlPanelEntityFeature(IntFlag): CONDITION_ARMED_NIGHT: Final = "is_armed_night" CONDITION_ARMED_VACATION: Final = "is_armed_vacation" CONDITION_ARMED_CUSTOM_BYPASS: Final = "is_armed_custom_bypass" + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index 4e6fa477ed2ba..efad44b15ef37 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -58,6 +58,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.deprecation import ( DeprecatedConstant, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -147,10 +148,6 @@ def __call__(self, variables: Mapping[str, Any] | None = None) -> bool: TriggerInfo, "TriggerInfo", "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - @bind_hass def is_on(hass: HomeAssistant, entity_id: str) -> bool: @@ -1108,3 +1105,11 @@ def websocket_config( "config": automation.raw_config, }, ) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/binary_sensor/__init__.py b/homeassistant/components/binary_sensor/__init__.py index 3a32a1afb57c5..0618548941948 100644 --- a/homeassistant/components/binary_sensor/__init__.py +++ b/homeassistant/components/binary_sensor/__init__.py @@ -19,6 +19,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -218,10 +219,6 @@ class BinarySensorDeviceClass(StrEnum): BinarySensorDeviceClass.WINDOW, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - # mypy: disallow-any-generics @@ -303,3 +300,11 @@ def state(self) -> Literal["on", "off"] | None: if (is_on := self.is_on) is None: return None return STATE_ON if is_on else STATE_OFF + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index c5dec12fe4014..7308f3a83ff71 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -20,6 +20,6 @@ "bluetooth-auto-recovery==1.2.3", "bluetooth-data-tools==1.19.0", "dbus-fast==2.21.0", - "habluetooth==2.0.1" + "habluetooth==2.0.2" ] } diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index 7a56292f7bb72..ce75f064d4765 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -54,6 +54,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -123,10 +124,6 @@ class CameraEntityFeature(IntFlag): CameraEntityFeature.STREAM, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - RTSP_PREFIXES = {"rtsp://", "rtsps://", "rtmp://"} DEFAULT_CONTENT_TYPE: Final = "image/jpeg" @@ -1082,3 +1079,11 @@ async def async_handle_record_service( duration=service_call.data[CONF_DURATION], lookback=service_call.data[CONF_LOOKBACK], ) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/camera/const.py b/homeassistant/components/camera/const.py index da41c0b9fabc7..09c4c7c1fb21d 100644 --- a/homeassistant/components/camera/const.py +++ b/homeassistant/components/camera/const.py @@ -5,6 +5,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -47,6 +48,9 @@ class StreamType(StrEnum): _DEPRECATED_STREAM_TYPE_WEB_RTC = DeprecatedConstantEnum(StreamType.WEB_RTC, "2025.1") -# Both can be removed if no deprecated constant are in this module anymore +# These can be removed if no deprecated constant are in this module anymore __getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index 78cb92944cbf8..c315765925f43 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -28,6 +28,7 @@ make_entity_service_schema, ) from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -141,12 +142,6 @@ ), ) -# As we import deprecated constants from the const module, we need to add these two functions -# otherwise this module will be logged for using deprecated constants and not the custom component -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - # mypy: disallow-any-generics @@ -734,3 +729,13 @@ async def async_service_temperature_set( kwargs[value] = temp await entity.async_set_temperature(**kwargs) + + +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/climate/const.py b/homeassistant/components/climate/const.py index 615dc7d48dde5..9c9153d9f6320 100644 --- a/homeassistant/components/climate/const.py +++ b/homeassistant/components/climate/const.py @@ -5,6 +5,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -188,6 +189,9 @@ class ClimateEntityFeature(IntFlag): ClimateEntityFeature.AUX_HEAT, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore +# These can be removed if no deprecated constant are in this module anymore __getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/cloud/__init__.py b/homeassistant/components/cloud/__init__.py index d7d57835e3ade..6e5cddd0f2876 100644 --- a/homeassistant/components/cloud/__init__.py +++ b/homeassistant/components/cloud/__init__.py @@ -5,6 +5,7 @@ from collections.abc import Awaitable, Callable from datetime import datetime, timedelta from enum import Enum +from typing import cast from hass_nabucasa import Cloud import voluptuous as vol @@ -176,6 +177,22 @@ def async_active_subscription(hass: HomeAssistant) -> bool: return async_is_logged_in(hass) and not hass.data[DOMAIN].subscription_expired +async def async_get_or_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str: + """Get or create a cloudhook.""" + if not async_is_connected(hass): + raise CloudNotConnected + + if not async_is_logged_in(hass): + raise CloudNotAvailable + + cloud: Cloud[CloudClient] = hass.data[DOMAIN] + cloudhooks = cloud.client.cloudhooks + if hook := cloudhooks.get(webhook_id): + return cast(str, hook["cloudhook_url"]) + + return await async_create_cloudhook(hass, webhook_id) + + @bind_hass async def async_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str: """Create a cloudhook.""" diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index 3e438fb4ca130..945585de52299 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -34,6 +34,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -143,10 +144,6 @@ class CoverEntityFeature(IntFlag): CoverEntityFeature.SET_TILT_POSITION, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - ATTR_CURRENT_POSITION = "current_position" ATTR_CURRENT_TILT_POSITION = "current_tilt_position" ATTR_POSITION = "position" @@ -493,3 +490,11 @@ def _get_toggle_function( if self._cover_is_last_toggle_direction_open: return fns["close"] return fns["open"] + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index b5ad4660cde21..adcc90cccbfe2 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -6,6 +6,7 @@ from homeassistant.const import ATTR_GPS_ACCURACY, STATE_HOME # noqa: F401 from homeassistant.core import HomeAssistant from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -57,12 +58,6 @@ see, ) -# As we import deprecated constants from the const module, we need to add these two functions -# otherwise this module will be logged for using deprecated constants and not the custom component -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - @bind_hass def is_on(hass: HomeAssistant, entity_id: str) -> bool: @@ -83,3 +78,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: await async_setup_legacy_integration(hass, config) return True + + +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/device_tracker/const.py b/homeassistant/components/device_tracker/const.py index 10c16e0910702..67a90ab0f9522 100644 --- a/homeassistant/components/device_tracker/const.py +++ b/homeassistant/components/device_tracker/const.py @@ -9,6 +9,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -44,10 +45,6 @@ class SourceType(StrEnum): SourceType.BLUETOOTH_LE, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - CONF_SCAN_INTERVAL: Final = "interval_seconds" SCAN_INTERVAL: Final = timedelta(seconds=12) @@ -71,3 +68,10 @@ class SourceType(StrEnum): ATTR_IP: Final = "ip" CONNECTED_DEVICE_REGISTERED: Final = "device_tracker_connected_device_registered" + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/drop_connect/manifest.json b/homeassistant/components/drop_connect/manifest.json index f65c1848aff00..5df34fce561c9 100644 --- a/homeassistant/components/drop_connect/manifest.json +++ b/homeassistant/components/drop_connect/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/drop_connect", "iot_class": "local_push", "mqtt": ["drop_connect/discovery/#"], - "requirements": ["dropmqttapi==1.0.1"] + "requirements": ["dropmqttapi==1.0.2"] } diff --git a/homeassistant/components/enigma2/manifest.json b/homeassistant/components/enigma2/manifest.json index 7909db3b7c7fc..42fbcb5b9bc60 100644 --- a/homeassistant/components/enigma2/manifest.json +++ b/homeassistant/components/enigma2/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/enigma2", "iot_class": "local_polling", "loggers": ["openwebif"], - "requirements": ["openwebifpy==4.0.2"] + "requirements": ["openwebifpy==4.0.4"] } diff --git a/homeassistant/components/fan/__init__.py b/homeassistant/components/fan/__init__.py index dedaedfe60002..c35d828e3984e 100644 --- a/homeassistant/components/fan/__init__.py +++ b/homeassistant/components/fan/__init__.py @@ -26,6 +26,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -76,10 +77,6 @@ class FanEntityFeature(IntFlag): FanEntityFeature.PRESET_MODE, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - SERVICE_INCREASE_SPEED = "increase_speed" SERVICE_DECREASE_SPEED = "decrease_speed" SERVICE_OSCILLATE = "oscillate" @@ -471,3 +468,11 @@ def preset_modes(self) -> list[str] | None: if hasattr(self, "_attr_preset_modes"): return self._attr_preset_modes return None + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index 63f9f593ea887..bad73d913206b 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -1063,6 +1063,7 @@ class SwitchInfo(TypedDict): type: str callback_update: Callable callback_switch: Callable + init_state: bool class FritzBoxBaseEntity: diff --git a/homeassistant/components/fritz/switch.py b/homeassistant/components/fritz/switch.py index 026c0f3d6fbfe..c3da6b5af0b8b 100644 --- a/homeassistant/components/fritz/switch.py +++ b/homeassistant/components/fritz/switch.py @@ -166,9 +166,7 @@ async def _async_wifi_entities_list( _LOGGER.debug("WiFi networks list: %s", networks) return [ - FritzBoxWifiSwitch( - avm_wrapper, device_friendly_name, index, data["switch_name"] - ) + FritzBoxWifiSwitch(avm_wrapper, device_friendly_name, index, data) for index, data in networks.items() ] @@ -310,18 +308,16 @@ async def async_turn_off(self, **kwargs: Any) -> None: await self._async_handle_turn_on_off(turn_on=False) -class FritzBoxBaseSwitch(FritzBoxBaseEntity): +class FritzBoxBaseSwitch(FritzBoxBaseEntity, SwitchEntity): """Fritz switch base class.""" - _attr_is_on: bool | None = False - def __init__( self, avm_wrapper: AvmWrapper, device_friendly_name: str, switch_info: SwitchInfo, ) -> None: - """Init Fritzbox port switch.""" + """Init Fritzbox base switch.""" super().__init__(avm_wrapper, device_friendly_name) self._description = switch_info["description"] @@ -330,6 +326,7 @@ def __init__( self._type = switch_info["type"] self._update = switch_info["callback_update"] self._switch = switch_info["callback_switch"] + self._attr_is_on = switch_info["init_state"] self._name = f"{self._friendly_name} {self._description}" self._unique_id = f"{self._avm_wrapper.unique_id}-{slugify(self._description)}" @@ -381,7 +378,7 @@ async def _async_handle_turn_on_off(self, turn_on: bool) -> None: self._attr_is_on = turn_on -class FritzBoxPortSwitch(FritzBoxBaseSwitch, SwitchEntity): +class FritzBoxPortSwitch(FritzBoxBaseSwitch): """Defines a FRITZ!Box Tools PortForward switch.""" def __init__( @@ -412,6 +409,7 @@ def __init__( type=SWITCH_TYPE_PORTFORWARD, callback_update=self._async_fetch_update, callback_switch=self._async_switch_on_off_executor, + init_state=port_mapping["NewEnabled"], ) super().__init__(avm_wrapper, device_friendly_name, switch_info) @@ -553,7 +551,7 @@ async def _async_handle_turn_on_off(self, turn_on: bool) -> bool: return True -class FritzBoxWifiSwitch(FritzBoxBaseSwitch, SwitchEntity): +class FritzBoxWifiSwitch(FritzBoxBaseSwitch): """Defines a FRITZ!Box Tools Wifi switch.""" def __init__( @@ -561,7 +559,7 @@ def __init__( avm_wrapper: AvmWrapper, device_friendly_name: str, network_num: int, - network_name: str, + network_data: dict, ) -> None: """Init Fritz Wifi switch.""" self._avm_wrapper = avm_wrapper @@ -571,12 +569,13 @@ def __init__( self._network_num = network_num switch_info = SwitchInfo( - description=f"Wi-Fi {network_name}", + description=f"Wi-Fi {network_data['switch_name']}", friendly_name=device_friendly_name, icon="mdi:wifi", type=SWITCH_TYPE_WIFINETWORK, callback_update=self._async_fetch_update, callback_switch=self._async_switch_on_off_executor, + init_state=network_data["enabled"], ) super().__init__(self._avm_wrapper, device_friendly_name, switch_info) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 52f3932237b84..ad24f6bb12d79 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20240103.3"] + "requirements": ["home-assistant-frontend==20240104.0"] } diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index edb81c14a7279..4af79a6f811b2 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==3.1.1"], + "requirements": ["aiohomekit==3.1.2"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/homeassistant/components/humidifier/__init__.py b/homeassistant/components/humidifier/__init__.py index 75d4f0fd22507..65a8cd9d1d05d 100644 --- a/homeassistant/components/humidifier/__init__.py +++ b/homeassistant/components/humidifier/__init__.py @@ -24,6 +24,7 @@ PLATFORM_SCHEMA_BASE, ) from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -81,12 +82,6 @@ class HumidifierDeviceClass(StrEnum): # use the HumidifierDeviceClass enum instead. DEVICE_CLASSES = [cls.value for cls in HumidifierDeviceClass] -# As we import deprecated constants from the const module, we need to add these two functions -# otherwise this module will be logged for using deprecated constants and not the custom component -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - # mypy: disallow-any-generics @@ -214,7 +209,7 @@ def state_attributes(self) -> dict[str, Any]: if self.target_humidity is not None: data[ATTR_HUMIDITY] = self.target_humidity - if HumidifierEntityFeature.MODES in self.supported_features: + if HumidifierEntityFeature.MODES in self.supported_features_compat: data[ATTR_MODE] = self.mode return data @@ -293,3 +288,13 @@ def supported_features_compat(self) -> HumidifierEntityFeature: self._report_deprecated_supported_features_values(new_features) return new_features return features + + +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/humidifier/const.py b/homeassistant/components/humidifier/const.py index a1a219ddce764..66ac0fcf18d36 100644 --- a/homeassistant/components/humidifier/const.py +++ b/homeassistant/components/humidifier/const.py @@ -5,6 +5,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstant, DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -66,6 +67,9 @@ class HumidifierEntityFeature(IntFlag): HumidifierEntityFeature.MODES, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore +# These can be removed if no deprecated constant are in this module anymore __getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/lock/__init__.py b/homeassistant/components/lock/__init__.py index a9370f8d09266..a4e7c4b7d1ad4 100644 --- a/homeassistant/components/lock/__init__.py +++ b/homeassistant/components/lock/__init__.py @@ -33,6 +33,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -70,10 +71,6 @@ class LockEntityFeature(IntFlag): # Please use the LockEntityFeature enum instead. _DEPRECATED_SUPPORT_OPEN = DeprecatedConstantEnum(LockEntityFeature.OPEN, "2025.1") -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - PROP_TO_ATTR = {"changed_by": ATTR_CHANGED_BY, "code_format": ATTR_CODE_FORMAT} # mypy: disallow-any-generics @@ -315,3 +312,11 @@ def _async_read_entity_options(self) -> None: return self._lock_option_default_code = "" + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/mobile_app/__init__.py b/homeassistant/components/mobile_app/__init__.py index cb5c0ae5c3ddd..124ef750baa12 100644 --- a/homeassistant/components/mobile_app/__init__.py +++ b/homeassistant/components/mobile_app/__init__.py @@ -36,6 +36,7 @@ ) from .helpers import savable_state from .http_api import RegistrationsView +from .util import async_create_cloud_hook from .webhook import handle_webhook PLATFORMS = [Platform.SENSOR, Platform.BINARY_SENSOR, Platform.DEVICE_TRACKER] @@ -103,26 +104,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: registration_name = f"Mobile App: {registration[ATTR_DEVICE_NAME]}" webhook_register(hass, DOMAIN, registration_name, webhook_id, handle_webhook) - async def create_cloud_hook() -> None: - """Create a cloud hook.""" - hook = await cloud.async_create_cloudhook(hass, webhook_id) - hass.config_entries.async_update_entry( - entry, data={**entry.data, CONF_CLOUDHOOK_URL: hook} - ) - async def manage_cloudhook(state: cloud.CloudConnectionState) -> None: if ( state is cloud.CloudConnectionState.CLOUD_CONNECTED and CONF_CLOUDHOOK_URL not in entry.data ): - await create_cloud_hook() + await async_create_cloud_hook(hass, webhook_id, entry) if ( CONF_CLOUDHOOK_URL not in entry.data and cloud.async_active_subscription(hass) and cloud.async_is_connected(hass) ): - await create_cloud_hook() + await async_create_cloud_hook(hass, webhook_id, entry) + entry.async_on_unload(cloud.async_listen_connection_change(hass, manage_cloudhook)) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/mobile_app/http_api.py b/homeassistant/components/mobile_app/http_api.py index 3c34a291df15e..92bb473d51acd 100644 --- a/homeassistant/components/mobile_app/http_api.py +++ b/homeassistant/components/mobile_app/http_api.py @@ -35,6 +35,7 @@ SCHEMA_APP_DATA, ) from .helpers import supports_encryption +from .util import async_create_cloud_hook class RegistrationsView(HomeAssistantView): @@ -69,8 +70,8 @@ async def post(self, request: Request, data: dict) -> Response: webhook_id = secrets.token_hex() if cloud.async_active_subscription(hass): - data[CONF_CLOUDHOOK_URL] = await cloud.async_create_cloudhook( - hass, webhook_id + data[CONF_CLOUDHOOK_URL] = await async_create_cloud_hook( + hass, webhook_id, None ) data[CONF_WEBHOOK_ID] = webhook_id diff --git a/homeassistant/components/mobile_app/util.py b/homeassistant/components/mobile_app/util.py index 45641861e5cd6..a7871d935edf3 100644 --- a/homeassistant/components/mobile_app/util.py +++ b/homeassistant/components/mobile_app/util.py @@ -1,8 +1,11 @@ """Mobile app utility functions.""" from __future__ import annotations +import asyncio from typing import TYPE_CHECKING +from homeassistant.components import cloud +from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from .const import ( @@ -10,6 +13,7 @@ ATTR_PUSH_TOKEN, ATTR_PUSH_URL, ATTR_PUSH_WEBSOCKET_CHANNEL, + CONF_CLOUDHOOK_URL, DATA_CONFIG_ENTRIES, DATA_DEVICES, DATA_NOTIFY, @@ -53,3 +57,19 @@ def get_notify_service(hass: HomeAssistant, webhook_id: str) -> str | None: return target_service return None + + +_CLOUD_HOOK_LOCK = asyncio.Lock() + + +async def async_create_cloud_hook( + hass: HomeAssistant, webhook_id: str, entry: ConfigEntry | None +) -> str: + """Create a cloud hook.""" + async with _CLOUD_HOOK_LOCK: + hook = await cloud.async_get_or_create_cloudhook(hass, webhook_id) + if entry: + hass.config_entries.async_update_entry( + entry, data={**entry.data, CONF_CLOUDHOOK_URL: hook} + ) + return hook diff --git a/homeassistant/components/number/const.py b/homeassistant/components/number/const.py index 55d22c8664893..a2d7c066af75f 100644 --- a/homeassistant/components/number/const.py +++ b/homeassistant/components/number/const.py @@ -38,6 +38,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -70,10 +71,6 @@ class NumberMode(StrEnum): _DEPRECATED_MODE_BOX: Final = DeprecatedConstantEnum(NumberMode.BOX, "2025.1") _DEPRECATED_MODE_SLIDER: Final = DeprecatedConstantEnum(NumberMode.SLIDER, "2025.1") -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - class NumberDeviceClass(StrEnum): """Device class for numbers.""" @@ -481,3 +478,10 @@ class NumberDeviceClass(StrEnum): UNIT_CONVERTERS: dict[str, type[BaseUnitConverter]] = { NumberDeviceClass.TEMPERATURE: TemperatureConverter, } + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/opower/config_flow.py b/homeassistant/components/opower/config_flow.py index d456fc536e58f..ab1fbbe36e3b5 100644 --- a/homeassistant/components/opower/config_flow.py +++ b/homeassistant/components/opower/config_flow.py @@ -3,6 +3,7 @@ from collections.abc import Mapping import logging +import socket from typing import Any from opower import ( @@ -38,7 +39,7 @@ async def _validate_login( ) -> dict[str, str]: """Validate login data and return any errors.""" api = Opower( - async_create_clientsession(hass), + async_create_clientsession(hass, family=socket.AF_INET), login_data[CONF_UTILITY], login_data[CONF_USERNAME], login_data[CONF_PASSWORD], diff --git a/homeassistant/components/opower/coordinator.py b/homeassistant/components/opower/coordinator.py index a474255e34dce..73c60068cd457 100644 --- a/homeassistant/components/opower/coordinator.py +++ b/homeassistant/components/opower/coordinator.py @@ -1,6 +1,7 @@ """Coordinator to handle Opower connections.""" from datetime import datetime, timedelta import logging +import socket from types import MappingProxyType from typing import Any, cast @@ -51,7 +52,7 @@ def __init__( update_interval=timedelta(hours=12), ) self.api = Opower( - aiohttp_client.async_get_clientsession(hass), + aiohttp_client.async_get_clientsession(hass, family=socket.AF_INET), entry_data[CONF_UTILITY], entry_data[CONF_USERNAME], entry_data[CONF_PASSWORD], diff --git a/homeassistant/components/orvibo/manifest.json b/homeassistant/components/orvibo/manifest.json index 72cdc4118dffa..05ce5edd8bd31 100644 --- a/homeassistant/components/orvibo/manifest.json +++ b/homeassistant/components/orvibo/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/orvibo", "iot_class": "local_push", "loggers": ["orvibo"], - "requirements": ["orvibo==1.1.1"] + "requirements": ["orvibo==1.1.2"] } diff --git a/homeassistant/components/qbittorrent/sensor.py b/homeassistant/components/qbittorrent/sensor.py index 9373aec85444d..78e8ba59d44ee 100644 --- a/homeassistant/components/qbittorrent/sensor.py +++ b/homeassistant/components/qbittorrent/sensor.py @@ -165,6 +165,10 @@ def count_torrents_in_states( coordinator: QBittorrentDataCoordinator, states: list[str] ) -> int: """Count the number of torrents in specified states.""" + # When torrents are not in the returned data, there are none, return 0. + if "torrents" not in coordinator.data: + return 0 + if not states: return len(coordinator.data["torrents"]) diff --git a/homeassistant/components/remote/__init__.py b/homeassistant/components/remote/__init__.py index 7e9ebfe12b9f5..c5facb9785cc6 100644 --- a/homeassistant/components/remote/__init__.py +++ b/homeassistant/components/remote/__init__.py @@ -27,6 +27,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -92,10 +93,6 @@ class RemoteEntityFeature(IntFlag): ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - REMOTE_SERVICE_ACTIVITY_SCHEMA = make_entity_service_schema( {vol.Optional(ATTR_ACTIVITY): cv.string} ) @@ -262,3 +259,11 @@ async def async_delete_command(self, **kwargs: Any) -> None: await self.hass.async_add_executor_job( ft.partial(self.delete_command, **kwargs) ) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index d7c5cddc5db69..6498b92b03e95 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -59,6 +59,7 @@ PLATFORM_SCHEMA_BASE, ) from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -120,12 +121,6 @@ "SensorStateClass", ] -# As we import deprecated constants from the const module, we need to add these two functions -# otherwise this module will be logged for using deprecated constants and not the custom component -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - # mypy: disallow-any-generics @@ -955,3 +950,13 @@ def async_rounded_state(hass: HomeAssistant, entity_id: str, state: State) -> st value = f"{numerical_value:z.{precision}f}" return value + + +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/sensor/const.py b/homeassistant/components/sensor/const.py index d57a09981efba..b1cb120e3fee3 100644 --- a/homeassistant/components/sensor/const.py +++ b/homeassistant/components/sensor/const.py @@ -38,6 +38,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -468,10 +469,6 @@ class SensorStateClass(StrEnum): ) STATE_CLASSES: Final[list[str]] = [cls.value for cls in SensorStateClass] -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = { SensorDeviceClass.ATMOSPHERIC_PRESSURE: PressureConverter, SensorDeviceClass.CURRENT: ElectricCurrentConverter, @@ -631,3 +628,10 @@ class SensorStateClass(StrEnum): SensorDeviceClass.WEIGHT: {SensorStateClass.MEASUREMENT}, SensorDeviceClass.WIND_SPEED: {SensorStateClass.MEASUREMENT}, } + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/shelly/config_flow.py b/homeassistant/components/shelly/config_flow.py index 68b0f1f8cccb1..29daf05016370 100644 --- a/homeassistant/components/shelly/config_flow.py +++ b/homeassistant/components/shelly/config_flow.py @@ -25,6 +25,7 @@ from .const import ( CONF_BLE_SCANNER_MODE, + CONF_GEN, CONF_SLEEP_PERIOD, DOMAIN, LOGGER, @@ -84,7 +85,7 @@ async def validate_input( "title": rpc_device.name, CONF_SLEEP_PERIOD: sleep_period, "model": rpc_device.shelly.get("model"), - "gen": gen, + CONF_GEN: gen, } # Gen1 @@ -99,7 +100,7 @@ async def validate_input( "title": block_device.name, CONF_SLEEP_PERIOD: get_block_device_sleep_period(block_device.settings), "model": block_device.model, - "gen": gen, + CONF_GEN: gen, } @@ -153,7 +154,7 @@ async def async_step_user( **user_input, CONF_SLEEP_PERIOD: device_info[CONF_SLEEP_PERIOD], "model": device_info["model"], - "gen": device_info["gen"], + CONF_GEN: device_info[CONF_GEN], }, ) errors["base"] = "firmware_not_fully_provisioned" @@ -190,7 +191,7 @@ async def async_step_credentials( CONF_HOST: self.host, CONF_SLEEP_PERIOD: device_info[CONF_SLEEP_PERIOD], "model": device_info["model"], - "gen": device_info["gen"], + CONF_GEN: device_info[CONF_GEN], }, ) errors["base"] = "firmware_not_fully_provisioned" @@ -288,7 +289,7 @@ async def async_step_confirm_discovery( "host": self.host, CONF_SLEEP_PERIOD: self.device_info[CONF_SLEEP_PERIOD], "model": self.device_info["model"], - "gen": self.device_info["gen"], + CONF_GEN: self.device_info[CONF_GEN], }, ) self._set_confirm_only() @@ -321,7 +322,7 @@ async def async_step_reauth_confirm( except (DeviceConnectionError, InvalidAuthError, FirmwareUnsupported): return self.async_abort(reason="reauth_unsuccessful") - if self.entry.data.get("gen", 1) != 1: + if self.entry.data.get(CONF_GEN, 1) != 1: user_input[CONF_USERNAME] = "admin" try: await validate_input(self.hass, host, info, user_input) @@ -334,7 +335,7 @@ async def async_step_reauth_confirm( await self.hass.config_entries.async_reload(self.entry.entry_id) return self.async_abort(reason="reauth_successful") - if self.entry.data.get("gen", 1) in BLOCK_GENERATIONS: + if self.entry.data.get(CONF_GEN, 1) in BLOCK_GENERATIONS: schema = { vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str, @@ -363,7 +364,7 @@ def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlowHandler: def async_supports_options_flow(cls, config_entry: ConfigEntry) -> bool: """Return options flow support for this handler.""" return ( - config_entry.data.get("gen") in RPC_GENERATIONS + config_entry.data.get(CONF_GEN) in RPC_GENERATIONS and not config_entry.data.get(CONF_SLEEP_PERIOD) and config_entry.data.get("model") != MODEL_WALL_DISPLAY ) diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py index ca1c450c9faaa..1e2c22691fb6c 100644 --- a/homeassistant/components/shelly/const.py +++ b/homeassistant/components/shelly/const.py @@ -214,3 +214,5 @@ class BLEScannerMode(StrEnum): MODEL_MOTION_2, MODEL_VALVE, ) + +CONF_GEN = "gen" diff --git a/homeassistant/components/shelly/coordinator.py b/homeassistant/components/shelly/coordinator.py index a7659ecc392f9..77fa0bd2efd16 100644 --- a/homeassistant/components/shelly/coordinator.py +++ b/homeassistant/components/shelly/coordinator.py @@ -33,6 +33,7 @@ ATTR_GENERATION, BATTERY_DEVICES_WITH_PERMANENT_CONNECTION, CONF_BLE_SCANNER_MODE, + CONF_GEN, CONF_SLEEP_PERIOD, DATA_CONFIG_ENTRY, DOMAIN, @@ -135,7 +136,7 @@ def async_setup(self) -> None: manufacturer="Shelly", model=aioshelly.const.MODEL_NAMES.get(self.model, self.model), sw_version=self.sw_version, - hw_version=f"gen{self.device.gen} ({self.model})", + hw_version=f"gen{self.entry.data[CONF_GEN]} ({self.model})", configuration_url=f"http://{self.entry.data[CONF_HOST]}", ) self.device_id = device_entry.id diff --git a/homeassistant/components/shelly/utils.py b/homeassistant/components/shelly/utils.py index a43d9cb0bcb07..d40b22ca50a4f 100644 --- a/homeassistant/components/shelly/utils.py +++ b/homeassistant/components/shelly/utils.py @@ -34,6 +34,7 @@ from .const import ( BASIC_INPUTS_EVENTS_TYPES, CONF_COAP_PORT, + CONF_GEN, DEFAULT_COAP_PORT, DEVICES_WITHOUT_FIRMWARE_CHANGELOG, DOMAIN, @@ -281,7 +282,7 @@ def get_info_auth(info: dict[str, Any]) -> bool: def get_info_gen(info: dict[str, Any]) -> int: """Return the device generation from shelly info.""" - return int(info.get("gen", 1)) + return int(info.get(CONF_GEN, 1)) def get_model_name(info: dict[str, Any]) -> str: @@ -325,7 +326,7 @@ def get_rpc_entity_name( def get_device_entry_gen(entry: ConfigEntry) -> int: """Return the device generation from config entry.""" - return entry.data.get("gen", 1) + return entry.data.get(CONF_GEN, 1) def get_rpc_key_instances(keys_dict: dict[str, Any], key: str) -> list[str]: diff --git a/homeassistant/components/siren/__init__.py b/homeassistant/components/siren/__init__.py index 29ad238ac0047..fb41d5f7b4884 100644 --- a/homeassistant/components/siren/__init__.py +++ b/homeassistant/components/siren/__init__.py @@ -17,6 +17,7 @@ PLATFORM_SCHEMA_BASE, ) from homeassistant.helpers.deprecation import ( + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -53,12 +54,6 @@ vol.Optional(ATTR_VOLUME_LEVEL): cv.small_float, } -# As we import deprecated constants from the const module, we need to add these two functions -# otherwise this module will be logged for using deprecated constants and not the custom component -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - class SirenTurnOnServiceParameters(TypedDict, total=False): """Represent possible parameters to siren.turn_on service data dict type.""" @@ -218,3 +213,13 @@ def supported_features(self) -> SirenEntityFeature: self._report_deprecated_supported_features_values(new_features) return new_features return features + + +# As we import deprecated constants from the const module, we need to add these two functions +# otherwise this module will be logged for using deprecated constants and not the custom component +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/siren/const.py b/homeassistant/components/siren/const.py index 50c3af61c8dd6..9e46d8dc997b9 100644 --- a/homeassistant/components/siren/const.py +++ b/homeassistant/components/siren/const.py @@ -6,6 +6,7 @@ from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -47,6 +48,9 @@ class SirenEntityFeature(IntFlag): SirenEntityFeature.DURATION, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore +# These can be removed if no deprecated constant are in this module anymore __getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/streamlabswater/__init__.py b/homeassistant/components/streamlabswater/__init__.py index 986b5de8049e2..82e8777a7e1ae 100644 --- a/homeassistant/components/streamlabswater/__init__.py +++ b/homeassistant/components/streamlabswater/__init__.py @@ -112,7 +112,7 @@ def set_away_mode(service: ServiceCall) -> None: ) client.update_location(location_id, away_mode) - hass.services.register( + hass.services.async_register( DOMAIN, SERVICE_SET_AWAY_MODE, set_away_mode, schema=SET_AWAY_MODE_SCHEMA ) diff --git a/homeassistant/components/streamlabswater/coordinator.py b/homeassistant/components/streamlabswater/coordinator.py index a11eced5a6e5c..dc57ae78810a5 100644 --- a/homeassistant/components/streamlabswater/coordinator.py +++ b/homeassistant/components/streamlabswater/coordinator.py @@ -44,7 +44,7 @@ async def _async_update_data(self) -> dict[str, StreamlabsData]: def _update_data(self) -> dict[str, StreamlabsData]: locations = self.client.get_locations() res = {} - for location in locations: + for location in locations["locations"]: location_id = location["locationId"] water_usage = self.client.get_water_usage_summary(location_id) res[location_id] = StreamlabsData( diff --git a/homeassistant/components/streamlabswater/sensor.py b/homeassistant/components/streamlabswater/sensor.py index 0b249b7c4e54b..6c869a6d1bc95 100644 --- a/homeassistant/components/streamlabswater/sensor.py +++ b/homeassistant/components/streamlabswater/sensor.py @@ -27,7 +27,7 @@ async def async_setup_entry( entities = [] - for location_id in coordinator.data.values(): + for location_id in coordinator.data: entities.extend( [ StreamLabsDailyUsage(coordinator, location_id), diff --git a/homeassistant/components/switch/__init__.py b/homeassistant/components/switch/__init__.py index a318f763fcb70..ce9b1477ad6a2 100644 --- a/homeassistant/components/switch/__init__.py +++ b/homeassistant/components/switch/__init__.py @@ -23,6 +23,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -66,10 +67,6 @@ class SwitchDeviceClass(StrEnum): SwitchDeviceClass.SWITCH, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - # mypy: disallow-any-generics @@ -133,3 +130,11 @@ def device_class(self) -> SwitchDeviceClass | None: if hasattr(self, "entity_description"): return self.entity_description.device_class return None + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/tado/manifest.json b/homeassistant/components/tado/manifest.json index 467697fc8108d..bae637f31801c 100644 --- a/homeassistant/components/tado/manifest.json +++ b/homeassistant/components/tado/manifest.json @@ -14,5 +14,5 @@ }, "iot_class": "cloud_polling", "loggers": ["PyTado"], - "requirements": ["python-tado==0.17.0"] + "requirements": ["python-tado==0.17.3"] } diff --git a/homeassistant/components/tessie/coordinator.py b/homeassistant/components/tessie/coordinator.py index c2f53da53bc30..75cac088bde47 100644 --- a/homeassistant/components/tessie/coordinator.py +++ b/homeassistant/components/tessie/coordinator.py @@ -41,7 +41,6 @@ def __init__( self.vin = vin self.session = async_get_clientsession(hass) self.data = self._flatten(data) - self.did_first_update = False async def _async_update_data(self) -> dict[str, Any]: """Update vehicle data using Tessie API.""" @@ -50,7 +49,7 @@ async def _async_update_data(self) -> dict[str, Any]: session=self.session, api_key=self.api_key, vin=self.vin, - use_cache=self.did_first_update, + use_cache=False, ) except ClientResponseError as e: if e.status == HTTPStatus.UNAUTHORIZED: @@ -58,7 +57,6 @@ async def _async_update_data(self) -> dict[str, Any]: raise ConfigEntryAuthFailed from e raise e - self.did_first_update = True if vehicle["state"] == TessieStatus.ONLINE: # Vehicle is online, all data is fresh return self._flatten(vehicle) diff --git a/homeassistant/components/update/__init__.py b/homeassistant/components/update/__init__.py index 40431332aafed..8ec14b6e3a89f 100644 --- a/homeassistant/components/update/__init__.py +++ b/homeassistant/components/update/__init__.py @@ -140,7 +140,7 @@ async def async_install(entity: UpdateEntity, service_call: ServiceCall) -> None # If version is specified, but not supported by the entity. if ( version is not None - and UpdateEntityFeature.SPECIFIC_VERSION not in entity.supported_features + and UpdateEntityFeature.SPECIFIC_VERSION not in entity.supported_features_compat ): raise HomeAssistantError( f"Installing a specific version is not supported for {entity.entity_id}" @@ -149,7 +149,7 @@ async def async_install(entity: UpdateEntity, service_call: ServiceCall) -> None # If backup is requested, but not supported by the entity. if ( backup := service_call.data[ATTR_BACKUP] - ) and UpdateEntityFeature.BACKUP not in entity.supported_features: + ) and UpdateEntityFeature.BACKUP not in entity.supported_features_compat: raise HomeAssistantError(f"Backup is not supported for {entity.entity_id}") # Update is already in progress. diff --git a/homeassistant/components/water_heater/__init__.py b/homeassistant/components/water_heater/__init__.py index f274441690067..82a853125ff1f 100644 --- a/homeassistant/components/water_heater/__init__.py +++ b/homeassistant/components/water_heater/__init__.py @@ -30,6 +30,7 @@ ) from homeassistant.helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -86,10 +87,6 @@ class WaterHeaterEntityFeature(IntFlag): WaterHeaterEntityFeature.AWAY_MODE, "2025.1" ) -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = ft.partial(dir_with_deprecated_constants, module_globals=globals()) - ATTR_MAX_TEMP = "max_temp" ATTR_MIN_TEMP = "min_temp" ATTR_AWAY_MODE = "away_mode" @@ -241,7 +238,7 @@ def capability_attributes(self) -> Mapping[str, Any]: ), } - if WaterHeaterEntityFeature.OPERATION_MODE in self.supported_features: + if WaterHeaterEntityFeature.OPERATION_MODE in self.supported_features_compat: data[ATTR_OPERATION_LIST] = self.operation_list return data @@ -277,7 +274,7 @@ def state_attributes(self) -> dict[str, Any]: ), } - supported_features = self.supported_features + supported_features = self.supported_features_compat if WaterHeaterEntityFeature.OPERATION_MODE in supported_features: data[ATTR_OPERATION_MODE] = self.current_operation @@ -441,3 +438,11 @@ async def async_service_temperature_set( kwargs[value] = temp await entity.async_set_temperature(**kwargs) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = ft.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = ft.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/components/zwave_js/manifest.json b/homeassistant/components/zwave_js/manifest.json index 9a66dae8e9323..a06de5cb8eeba 100644 --- a/homeassistant/components/zwave_js/manifest.json +++ b/homeassistant/components/zwave_js/manifest.json @@ -9,7 +9,7 @@ "iot_class": "local_push", "loggers": ["zwave_js_server"], "quality_scale": "platinum", - "requirements": ["pyserial==3.5", "zwave-js-server-python==0.55.2"], + "requirements": ["pyserial==3.5", "zwave-js-server-python==0.55.3"], "usb": [ { "vid": "0658", diff --git a/homeassistant/const.py b/homeassistant/const.py index 6afa0430ba36f..cea73ec243b47 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,12 +2,21 @@ from __future__ import annotations from enum import StrEnum -from typing import Any, Final +from functools import partial +from typing import Final + +from .helpers.deprecation import ( + DeprecatedConstant, + DeprecatedConstantEnum, + all_with_deprecated_constants, + check_if_deprecated_constant, + dir_with_deprecated_constants, +) APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2024 MINOR_VERSION: Final = 1 -PATCH_VERSION: Final = "0" +PATCH_VERSION: Final = "1" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) @@ -307,148 +316,131 @@ class Platform(StrEnum): # #### DEVICE CLASSES #### # DEVICE_CLASS_* below are deprecated as of 2021.12 # use the SensorDeviceClass enum instead. -_DEPRECATED_DEVICE_CLASS_AQI: Final = ("aqi", "SensorDeviceClass.AQI", "2025.1") -_DEPRECATED_DEVICE_CLASS_BATTERY: Final = ( +_DEPRECATED_DEVICE_CLASS_AQI: Final = DeprecatedConstant( + "aqi", "SensorDeviceClass.AQI", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_BATTERY: Final = DeprecatedConstant( "battery", "SensorDeviceClass.BATTERY", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_CO: Final = ( +_DEPRECATED_DEVICE_CLASS_CO: Final = DeprecatedConstant( "carbon_monoxide", "SensorDeviceClass.CO", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_CO2: Final = ( +_DEPRECATED_DEVICE_CLASS_CO2: Final = DeprecatedConstant( "carbon_dioxide", "SensorDeviceClass.CO2", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_CURRENT: Final = ( +_DEPRECATED_DEVICE_CLASS_CURRENT: Final = DeprecatedConstant( "current", "SensorDeviceClass.CURRENT", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_DATE: Final = ("date", "SensorDeviceClass.DATE", "2025.1") -_DEPRECATED_DEVICE_CLASS_ENERGY: Final = ( +_DEPRECATED_DEVICE_CLASS_DATE: Final = DeprecatedConstant( + "date", "SensorDeviceClass.DATE", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_ENERGY: Final = DeprecatedConstant( "energy", "SensorDeviceClass.ENERGY", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_FREQUENCY: Final = ( +_DEPRECATED_DEVICE_CLASS_FREQUENCY: Final = DeprecatedConstant( "frequency", "SensorDeviceClass.FREQUENCY", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_GAS: Final = ("gas", "SensorDeviceClass.GAS", "2025.1") -_DEPRECATED_DEVICE_CLASS_HUMIDITY: Final = ( +_DEPRECATED_DEVICE_CLASS_GAS: Final = DeprecatedConstant( + "gas", "SensorDeviceClass.GAS", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_HUMIDITY: Final = DeprecatedConstant( "humidity", "SensorDeviceClass.HUMIDITY", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_ILLUMINANCE: Final = ( +_DEPRECATED_DEVICE_CLASS_ILLUMINANCE: Final = DeprecatedConstant( "illuminance", "SensorDeviceClass.ILLUMINANCE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_MONETARY: Final = ( +_DEPRECATED_DEVICE_CLASS_MONETARY: Final = DeprecatedConstant( "monetary", "SensorDeviceClass.MONETARY", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_NITROGEN_DIOXIDE = ( +_DEPRECATED_DEVICE_CLASS_NITROGEN_DIOXIDE: Final = DeprecatedConstant( "nitrogen_dioxide", "SensorDeviceClass.NITROGEN_DIOXIDE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_NITROGEN_MONOXIDE = ( +_DEPRECATED_DEVICE_CLASS_NITROGEN_MONOXIDE: Final = DeprecatedConstant( "nitrogen_monoxide", "SensorDeviceClass.NITROGEN_MONOXIDE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_NITROUS_OXIDE = ( +_DEPRECATED_DEVICE_CLASS_NITROUS_OXIDE: Final = DeprecatedConstant( "nitrous_oxide", "SensorDeviceClass.NITROUS_OXIDE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_OZONE: Final = ("ozone", "SensorDeviceClass.OZONE", "2025.1") -_DEPRECATED_DEVICE_CLASS_PM1: Final = ("pm1", "SensorDeviceClass.PM1", "2025.1") -_DEPRECATED_DEVICE_CLASS_PM10: Final = ("pm10", "SensorDeviceClass.PM10", "2025.1") -_DEPRECATED_DEVICE_CLASS_PM25: Final = ("pm25", "SensorDeviceClass.PM25", "2025.1") -_DEPRECATED_DEVICE_CLASS_POWER_FACTOR: Final = ( +_DEPRECATED_DEVICE_CLASS_OZONE: Final = DeprecatedConstant( + "ozone", "SensorDeviceClass.OZONE", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_PM1: Final = DeprecatedConstant( + "pm1", "SensorDeviceClass.PM1", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_PM10: Final = DeprecatedConstant( + "pm10", "SensorDeviceClass.PM10", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_PM25: Final = DeprecatedConstant( + "pm25", "SensorDeviceClass.PM25", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_POWER_FACTOR: Final = DeprecatedConstant( "power_factor", "SensorDeviceClass.POWER_FACTOR", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_POWER: Final = ("power", "SensorDeviceClass.POWER", "2025.1") -_DEPRECATED_DEVICE_CLASS_PRESSURE: Final = ( +_DEPRECATED_DEVICE_CLASS_POWER: Final = DeprecatedConstant( + "power", "SensorDeviceClass.POWER", "2025.1" +) +_DEPRECATED_DEVICE_CLASS_PRESSURE: Final = DeprecatedConstant( "pressure", "SensorDeviceClass.PRESSURE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_SIGNAL_STRENGTH: Final = ( +_DEPRECATED_DEVICE_CLASS_SIGNAL_STRENGTH: Final = DeprecatedConstant( "signal_strength", "SensorDeviceClass.SIGNAL_STRENGTH", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_SULPHUR_DIOXIDE = ( +_DEPRECATED_DEVICE_CLASS_SULPHUR_DIOXIDE: Final = DeprecatedConstant( "sulphur_dioxide", "SensorDeviceClass.SULPHUR_DIOXIDE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_TEMPERATURE: Final = ( +_DEPRECATED_DEVICE_CLASS_TEMPERATURE: Final = DeprecatedConstant( "temperature", "SensorDeviceClass.TEMPERATURE", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_TIMESTAMP: Final = ( +_DEPRECATED_DEVICE_CLASS_TIMESTAMP: Final = DeprecatedConstant( "timestamp", "SensorDeviceClass.TIMESTAMP", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS = ( +_DEPRECATED_DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS: Final = DeprecatedConstant( "volatile_organic_compounds", "SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS", "2025.1", ) -_DEPRECATED_DEVICE_CLASS_VOLTAGE: Final = ( +_DEPRECATED_DEVICE_CLASS_VOLTAGE: Final = DeprecatedConstant( "voltage", "SensorDeviceClass.VOLTAGE", "2025.1", ) - -# Can be removed if no deprecated constant are in this module anymore -def __getattr__(name: str) -> Any: - """Check if the not found name is a deprecated constant. - - If it is, print a deprecation warning and return the value of the constant. - Otherwise raise AttributeError. - """ - module_globals = globals() - if f"_DEPRECATED_{name}" not in module_globals: - raise AttributeError(f"Module {__name__} has no attribute {name!r}") - - # Avoid circular import - from .helpers.deprecation import ( # pylint: disable=import-outside-toplevel - check_if_deprecated_constant, - ) - - return check_if_deprecated_constant(name, module_globals) - - -# Can be removed if no deprecated constant are in this module anymore -def __dir__() -> list[str]: - """Return dir() with deprecated constants.""" - # Copied method from homeassistant.helpers.deprecattion#dir_with_deprecated_constants to avoid import cycle - module_globals = globals() - - return list(module_globals) + [ - name.removeprefix("_DEPRECATED_") - for name in module_globals - if name.startswith("_DEPRECATED_") - ] - - # #### STATES #### STATE_ON: Final = "on" STATE_OFF: Final = "off" @@ -621,7 +613,7 @@ class UnitOfApparentPower(StrEnum): VOLT_AMPERE = "VA" -_DEPRECATED_POWER_VOLT_AMPERE: Final = ( +_DEPRECATED_POWER_VOLT_AMPERE: Final = DeprecatedConstantEnum( UnitOfApparentPower.VOLT_AMPERE, "2025.1", ) @@ -637,17 +629,17 @@ class UnitOfPower(StrEnum): BTU_PER_HOUR = "BTU/h" -_DEPRECATED_POWER_WATT: Final = ( +_DEPRECATED_POWER_WATT: Final = DeprecatedConstantEnum( UnitOfPower.WATT, "2025.1", ) """Deprecated: please use UnitOfPower.WATT.""" -_DEPRECATED_POWER_KILO_WATT: Final = ( +_DEPRECATED_POWER_KILO_WATT: Final = DeprecatedConstantEnum( UnitOfPower.KILO_WATT, "2025.1", ) """Deprecated: please use UnitOfPower.KILO_WATT.""" -_DEPRECATED_POWER_BTU_PER_HOUR: Final = ( +_DEPRECATED_POWER_BTU_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfPower.BTU_PER_HOUR, "2025.1", ) @@ -668,17 +660,17 @@ class UnitOfEnergy(StrEnum): WATT_HOUR = "Wh" -_DEPRECATED_ENERGY_KILO_WATT_HOUR: Final = ( +_DEPRECATED_ENERGY_KILO_WATT_HOUR: Final = DeprecatedConstantEnum( UnitOfEnergy.KILO_WATT_HOUR, "2025.1", ) """Deprecated: please use UnitOfEnergy.KILO_WATT_HOUR.""" -_DEPRECATED_ENERGY_MEGA_WATT_HOUR: Final = ( +_DEPRECATED_ENERGY_MEGA_WATT_HOUR: Final = DeprecatedConstantEnum( UnitOfEnergy.MEGA_WATT_HOUR, "2025.1", ) """Deprecated: please use UnitOfEnergy.MEGA_WATT_HOUR.""" -_DEPRECATED_ENERGY_WATT_HOUR: Final = ( +_DEPRECATED_ENERGY_WATT_HOUR: Final = DeprecatedConstantEnum( UnitOfEnergy.WATT_HOUR, "2025.1", ) @@ -693,12 +685,12 @@ class UnitOfElectricCurrent(StrEnum): AMPERE = "A" -_DEPRECATED_ELECTRIC_CURRENT_MILLIAMPERE: Final = ( +_DEPRECATED_ELECTRIC_CURRENT_MILLIAMPERE: Final = DeprecatedConstantEnum( UnitOfElectricCurrent.MILLIAMPERE, "2025.1", ) """Deprecated: please use UnitOfElectricCurrent.MILLIAMPERE.""" -_DEPRECATED_ELECTRIC_CURRENT_AMPERE: Final = ( +_DEPRECATED_ELECTRIC_CURRENT_AMPERE: Final = DeprecatedConstantEnum( UnitOfElectricCurrent.AMPERE, "2025.1", ) @@ -713,12 +705,12 @@ class UnitOfElectricPotential(StrEnum): VOLT = "V" -_DEPRECATED_ELECTRIC_POTENTIAL_MILLIVOLT: Final = ( +_DEPRECATED_ELECTRIC_POTENTIAL_MILLIVOLT: Final = DeprecatedConstantEnum( UnitOfElectricPotential.MILLIVOLT, "2025.1", ) """Deprecated: please use UnitOfElectricPotential.MILLIVOLT.""" -_DEPRECATED_ELECTRIC_POTENTIAL_VOLT: Final = ( +_DEPRECATED_ELECTRIC_POTENTIAL_VOLT: Final = DeprecatedConstantEnum( UnitOfElectricPotential.VOLT, "2025.1", ) @@ -742,17 +734,17 @@ class UnitOfTemperature(StrEnum): KELVIN = "K" -_DEPRECATED_TEMP_CELSIUS: Final = ( +_DEPRECATED_TEMP_CELSIUS: Final = DeprecatedConstantEnum( UnitOfTemperature.CELSIUS, "2025.1", ) """Deprecated: please use UnitOfTemperature.CELSIUS""" -_DEPRECATED_TEMP_FAHRENHEIT: Final = ( +_DEPRECATED_TEMP_FAHRENHEIT: Final = DeprecatedConstantEnum( UnitOfTemperature.FAHRENHEIT, "2025.1", ) """Deprecated: please use UnitOfTemperature.FAHRENHEIT""" -_DEPRECATED_TEMP_KELVIN: Final = ( +_DEPRECATED_TEMP_KELVIN: Final = DeprecatedConstantEnum( UnitOfTemperature.KELVIN, "2025.1", ) @@ -774,47 +766,47 @@ class UnitOfTime(StrEnum): YEARS = "y" -_DEPRECATED_TIME_MICROSECONDS: Final = ( +_DEPRECATED_TIME_MICROSECONDS: Final = DeprecatedConstantEnum( UnitOfTime.MICROSECONDS, "2025.1", ) """Deprecated: please use UnitOfTime.MICROSECONDS.""" -_DEPRECATED_TIME_MILLISECONDS: Final = ( +_DEPRECATED_TIME_MILLISECONDS: Final = DeprecatedConstantEnum( UnitOfTime.MILLISECONDS, "2025.1", ) """Deprecated: please use UnitOfTime.MILLISECONDS.""" -_DEPRECATED_TIME_SECONDS: Final = ( +_DEPRECATED_TIME_SECONDS: Final = DeprecatedConstantEnum( UnitOfTime.SECONDS, "2025.1", ) """Deprecated: please use UnitOfTime.SECONDS.""" -_DEPRECATED_TIME_MINUTES: Final = ( +_DEPRECATED_TIME_MINUTES: Final = DeprecatedConstantEnum( UnitOfTime.MINUTES, "2025.1", ) """Deprecated: please use UnitOfTime.MINUTES.""" -_DEPRECATED_TIME_HOURS: Final = ( +_DEPRECATED_TIME_HOURS: Final = DeprecatedConstantEnum( UnitOfTime.HOURS, "2025.1", ) """Deprecated: please use UnitOfTime.HOURS.""" -_DEPRECATED_TIME_DAYS: Final = ( +_DEPRECATED_TIME_DAYS: Final = DeprecatedConstantEnum( UnitOfTime.DAYS, "2025.1", ) """Deprecated: please use UnitOfTime.DAYS.""" -_DEPRECATED_TIME_WEEKS: Final = ( +_DEPRECATED_TIME_WEEKS: Final = DeprecatedConstantEnum( UnitOfTime.WEEKS, "2025.1", ) """Deprecated: please use UnitOfTime.WEEKS.""" -_DEPRECATED_TIME_MONTHS: Final = ( +_DEPRECATED_TIME_MONTHS: Final = DeprecatedConstantEnum( UnitOfTime.MONTHS, "2025.1", ) """Deprecated: please use UnitOfTime.MONTHS.""" -_DEPRECATED_TIME_YEARS: Final = ( +_DEPRECATED_TIME_YEARS: Final = DeprecatedConstantEnum( UnitOfTime.YEARS, "2025.1", ) @@ -835,42 +827,42 @@ class UnitOfLength(StrEnum): MILES = "mi" -_DEPRECATED_LENGTH_MILLIMETERS: Final = ( +_DEPRECATED_LENGTH_MILLIMETERS: Final = DeprecatedConstantEnum( UnitOfLength.MILLIMETERS, "2025.1", ) """Deprecated: please use UnitOfLength.MILLIMETERS.""" -_DEPRECATED_LENGTH_CENTIMETERS: Final = ( +_DEPRECATED_LENGTH_CENTIMETERS: Final = DeprecatedConstantEnum( UnitOfLength.CENTIMETERS, "2025.1", ) """Deprecated: please use UnitOfLength.CENTIMETERS.""" -_DEPRECATED_LENGTH_METERS: Final = ( +_DEPRECATED_LENGTH_METERS: Final = DeprecatedConstantEnum( UnitOfLength.METERS, "2025.1", ) """Deprecated: please use UnitOfLength.METERS.""" -_DEPRECATED_LENGTH_KILOMETERS: Final = ( +_DEPRECATED_LENGTH_KILOMETERS: Final = DeprecatedConstantEnum( UnitOfLength.KILOMETERS, "2025.1", ) """Deprecated: please use UnitOfLength.KILOMETERS.""" -_DEPRECATED_LENGTH_INCHES: Final = ( +_DEPRECATED_LENGTH_INCHES: Final = DeprecatedConstantEnum( UnitOfLength.INCHES, "2025.1", ) """Deprecated: please use UnitOfLength.INCHES.""" -_DEPRECATED_LENGTH_FEET: Final = ( +_DEPRECATED_LENGTH_FEET: Final = DeprecatedConstantEnum( UnitOfLength.FEET, "2025.1", ) """Deprecated: please use UnitOfLength.FEET.""" -_DEPRECATED_LENGTH_YARD: Final = ( +_DEPRECATED_LENGTH_YARD: Final = DeprecatedConstantEnum( UnitOfLength.YARDS, "2025.1", ) """Deprecated: please use UnitOfLength.YARDS.""" -_DEPRECATED_LENGTH_MILES: Final = ( +_DEPRECATED_LENGTH_MILES: Final = DeprecatedConstantEnum( UnitOfLength.MILES, "2025.1", ) @@ -887,22 +879,22 @@ class UnitOfFrequency(StrEnum): GIGAHERTZ = "GHz" -_DEPRECATED_FREQUENCY_HERTZ: Final = ( +_DEPRECATED_FREQUENCY_HERTZ: Final = DeprecatedConstantEnum( UnitOfFrequency.HERTZ, "2025.1", ) """Deprecated: please use UnitOfFrequency.HERTZ""" -_DEPRECATED_FREQUENCY_KILOHERTZ: Final = ( +_DEPRECATED_FREQUENCY_KILOHERTZ: Final = DeprecatedConstantEnum( UnitOfFrequency.KILOHERTZ, "2025.1", ) """Deprecated: please use UnitOfFrequency.KILOHERTZ""" -_DEPRECATED_FREQUENCY_MEGAHERTZ: Final = ( +_DEPRECATED_FREQUENCY_MEGAHERTZ: Final = DeprecatedConstantEnum( UnitOfFrequency.MEGAHERTZ, "2025.1", ) """Deprecated: please use UnitOfFrequency.MEGAHERTZ""" -_DEPRECATED_FREQUENCY_GIGAHERTZ: Final = ( +_DEPRECATED_FREQUENCY_GIGAHERTZ: Final = DeprecatedConstantEnum( UnitOfFrequency.GIGAHERTZ, "2025.1", ) @@ -924,47 +916,47 @@ class UnitOfPressure(StrEnum): PSI = "psi" -_DEPRECATED_PRESSURE_PA: Final = ( +_DEPRECATED_PRESSURE_PA: Final = DeprecatedConstantEnum( UnitOfPressure.PA, "2025.1", ) """Deprecated: please use UnitOfPressure.PA""" -_DEPRECATED_PRESSURE_HPA: Final = ( +_DEPRECATED_PRESSURE_HPA: Final = DeprecatedConstantEnum( UnitOfPressure.HPA, "2025.1", ) """Deprecated: please use UnitOfPressure.HPA""" -_DEPRECATED_PRESSURE_KPA: Final = ( +_DEPRECATED_PRESSURE_KPA: Final = DeprecatedConstantEnum( UnitOfPressure.KPA, "2025.1", ) """Deprecated: please use UnitOfPressure.KPA""" -_DEPRECATED_PRESSURE_BAR: Final = ( +_DEPRECATED_PRESSURE_BAR: Final = DeprecatedConstantEnum( UnitOfPressure.BAR, "2025.1", ) """Deprecated: please use UnitOfPressure.BAR""" -_DEPRECATED_PRESSURE_CBAR: Final = ( +_DEPRECATED_PRESSURE_CBAR: Final = DeprecatedConstantEnum( UnitOfPressure.CBAR, "2025.1", ) """Deprecated: please use UnitOfPressure.CBAR""" -_DEPRECATED_PRESSURE_MBAR: Final = ( +_DEPRECATED_PRESSURE_MBAR: Final = DeprecatedConstantEnum( UnitOfPressure.MBAR, "2025.1", ) """Deprecated: please use UnitOfPressure.MBAR""" -_DEPRECATED_PRESSURE_MMHG: Final = ( +_DEPRECATED_PRESSURE_MMHG: Final = DeprecatedConstantEnum( UnitOfPressure.MMHG, "2025.1", ) """Deprecated: please use UnitOfPressure.MMHG""" -_DEPRECATED_PRESSURE_INHG: Final = ( +_DEPRECATED_PRESSURE_INHG: Final = DeprecatedConstantEnum( UnitOfPressure.INHG, "2025.1", ) """Deprecated: please use UnitOfPressure.INHG""" -_DEPRECATED_PRESSURE_PSI: Final = ( +_DEPRECATED_PRESSURE_PSI: Final = DeprecatedConstantEnum( UnitOfPressure.PSI, "2025.1", ) @@ -979,12 +971,12 @@ class UnitOfSoundPressure(StrEnum): WEIGHTED_DECIBEL_A = "dBA" -_DEPRECATED_SOUND_PRESSURE_DB: Final = ( +_DEPRECATED_SOUND_PRESSURE_DB: Final = DeprecatedConstantEnum( UnitOfSoundPressure.DECIBEL, "2025.1", ) """Deprecated: please use UnitOfSoundPressure.DECIBEL""" -_DEPRECATED_SOUND_PRESSURE_WEIGHTED_DBA: Final = ( +_DEPRECATED_SOUND_PRESSURE_WEIGHTED_DBA: Final = DeprecatedConstantEnum( UnitOfSoundPressure.WEIGHTED_DECIBEL_A, "2025.1", ) @@ -1010,33 +1002,33 @@ class UnitOfVolume(StrEnum): British/Imperial fluid ounces are not yet supported""" -_DEPRECATED_VOLUME_LITERS: Final = ( +_DEPRECATED_VOLUME_LITERS: Final = DeprecatedConstantEnum( UnitOfVolume.LITERS, "2025.1", ) """Deprecated: please use UnitOfVolume.LITERS""" -_DEPRECATED_VOLUME_MILLILITERS: Final = ( +_DEPRECATED_VOLUME_MILLILITERS: Final = DeprecatedConstantEnum( UnitOfVolume.MILLILITERS, "2025.1", ) """Deprecated: please use UnitOfVolume.MILLILITERS""" -_DEPRECATED_VOLUME_CUBIC_METERS: Final = ( +_DEPRECATED_VOLUME_CUBIC_METERS: Final = DeprecatedConstantEnum( UnitOfVolume.CUBIC_METERS, "2025.1", ) """Deprecated: please use UnitOfVolume.CUBIC_METERS""" -_DEPRECATED_VOLUME_CUBIC_FEET: Final = ( +_DEPRECATED_VOLUME_CUBIC_FEET: Final = DeprecatedConstantEnum( UnitOfVolume.CUBIC_FEET, "2025.1", ) """Deprecated: please use UnitOfVolume.CUBIC_FEET""" -_DEPRECATED_VOLUME_GALLONS: Final = ( +_DEPRECATED_VOLUME_GALLONS: Final = DeprecatedConstantEnum( UnitOfVolume.GALLONS, "2025.1", ) """Deprecated: please use UnitOfVolume.GALLONS""" -_DEPRECATED_VOLUME_FLUID_OUNCE: Final = ( +_DEPRECATED_VOLUME_FLUID_OUNCE: Final = DeprecatedConstantEnum( UnitOfVolume.FLUID_OUNCES, "2025.1", ) @@ -1051,12 +1043,12 @@ class UnitOfVolumeFlowRate(StrEnum): CUBIC_FEET_PER_MINUTE = "ft³/m" -_DEPRECATED_VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR: Final = ( +_DEPRECATED_VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR, "2025.1", ) """Deprecated: please use UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR""" -_DEPRECATED_VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE: Final = ( +_DEPRECATED_VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE: Final = DeprecatedConstantEnum( UnitOfVolumeFlowRate.CUBIC_FEET_PER_MINUTE, "2025.1", ) @@ -1079,32 +1071,32 @@ class UnitOfMass(StrEnum): STONES = "st" -_DEPRECATED_MASS_GRAMS: Final = ( +_DEPRECATED_MASS_GRAMS: Final = DeprecatedConstantEnum( UnitOfMass.GRAMS, "2025.1", ) """Deprecated: please use UnitOfMass.GRAMS""" -_DEPRECATED_MASS_KILOGRAMS: Final = ( +_DEPRECATED_MASS_KILOGRAMS: Final = DeprecatedConstantEnum( UnitOfMass.KILOGRAMS, "2025.1", ) """Deprecated: please use UnitOfMass.KILOGRAMS""" -_DEPRECATED_MASS_MILLIGRAMS: Final = ( +_DEPRECATED_MASS_MILLIGRAMS: Final = DeprecatedConstantEnum( UnitOfMass.MILLIGRAMS, "2025.1", ) """Deprecated: please use UnitOfMass.MILLIGRAMS""" -_DEPRECATED_MASS_MICROGRAMS: Final = ( +_DEPRECATED_MASS_MICROGRAMS: Final = DeprecatedConstantEnum( UnitOfMass.MICROGRAMS, "2025.1", ) """Deprecated: please use UnitOfMass.MICROGRAMS""" -_DEPRECATED_MASS_OUNCES: Final = ( +_DEPRECATED_MASS_OUNCES: Final = DeprecatedConstantEnum( UnitOfMass.OUNCES, "2025.1", ) """Deprecated: please use UnitOfMass.OUNCES""" -_DEPRECATED_MASS_POUNDS: Final = ( +_DEPRECATED_MASS_POUNDS: Final = DeprecatedConstantEnum( UnitOfMass.POUNDS, "2025.1", ) @@ -1135,12 +1127,12 @@ class UnitOfIrradiance(StrEnum): # Irradiation units -_DEPRECATED_IRRADIATION_WATTS_PER_SQUARE_METER: Final = ( +_DEPRECATED_IRRADIATION_WATTS_PER_SQUARE_METER: Final = DeprecatedConstantEnum( UnitOfIrradiance.WATTS_PER_SQUARE_METER, "2025.1", ) """Deprecated: please use UnitOfIrradiance.WATTS_PER_SQUARE_METER""" -_DEPRECATED_IRRADIATION_BTUS_PER_HOUR_SQUARE_FOOT: Final = ( +_DEPRECATED_IRRADIATION_BTUS_PER_HOUR_SQUARE_FOOT: Final = DeprecatedConstantEnum( UnitOfIrradiance.BTUS_PER_HOUR_SQUARE_FOOT, "2025.1", ) @@ -1185,19 +1177,21 @@ class UnitOfPrecipitationDepth(StrEnum): # Precipitation units -_DEPRECATED_PRECIPITATION_INCHES: Final = (UnitOfPrecipitationDepth.INCHES, "2025.1") +_DEPRECATED_PRECIPITATION_INCHES: Final = DeprecatedConstantEnum( + UnitOfPrecipitationDepth.INCHES, "2025.1" +) """Deprecated: please use UnitOfPrecipitationDepth.INCHES""" -_DEPRECATED_PRECIPITATION_MILLIMETERS: Final = ( +_DEPRECATED_PRECIPITATION_MILLIMETERS: Final = DeprecatedConstantEnum( UnitOfPrecipitationDepth.MILLIMETERS, "2025.1", ) """Deprecated: please use UnitOfPrecipitationDepth.MILLIMETERS""" -_DEPRECATED_PRECIPITATION_MILLIMETERS_PER_HOUR: Final = ( +_DEPRECATED_PRECIPITATION_MILLIMETERS_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR, "2025.1", ) """Deprecated: please use UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR""" -_DEPRECATED_PRECIPITATION_INCHES_PER_HOUR: Final = ( +_DEPRECATED_PRECIPITATION_INCHES_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfVolumetricFlux.INCHES_PER_HOUR, "2025.1", ) @@ -1223,33 +1217,39 @@ class UnitOfSpeed(StrEnum): MILES_PER_HOUR = "mph" -_DEPRECATED_SPEED_FEET_PER_SECOND: Final = (UnitOfSpeed.FEET_PER_SECOND, "2025.1") +_DEPRECATED_SPEED_FEET_PER_SECOND: Final = DeprecatedConstantEnum( + UnitOfSpeed.FEET_PER_SECOND, "2025.1" +) """Deprecated: please use UnitOfSpeed.FEET_PER_SECOND""" -_DEPRECATED_SPEED_METERS_PER_SECOND: Final = (UnitOfSpeed.METERS_PER_SECOND, "2025.1") +_DEPRECATED_SPEED_METERS_PER_SECOND: Final = DeprecatedConstantEnum( + UnitOfSpeed.METERS_PER_SECOND, "2025.1" +) """Deprecated: please use UnitOfSpeed.METERS_PER_SECOND""" -_DEPRECATED_SPEED_KILOMETERS_PER_HOUR: Final = ( +_DEPRECATED_SPEED_KILOMETERS_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfSpeed.KILOMETERS_PER_HOUR, "2025.1", ) """Deprecated: please use UnitOfSpeed.KILOMETERS_PER_HOUR""" -_DEPRECATED_SPEED_KNOTS: Final = (UnitOfSpeed.KNOTS, "2025.1") +_DEPRECATED_SPEED_KNOTS: Final = DeprecatedConstantEnum(UnitOfSpeed.KNOTS, "2025.1") """Deprecated: please use UnitOfSpeed.KNOTS""" -_DEPRECATED_SPEED_MILES_PER_HOUR: Final = (UnitOfSpeed.MILES_PER_HOUR, "2025.1") +_DEPRECATED_SPEED_MILES_PER_HOUR: Final = DeprecatedConstantEnum( + UnitOfSpeed.MILES_PER_HOUR, "2025.1" +) """Deprecated: please use UnitOfSpeed.MILES_PER_HOUR""" -_DEPRECATED_SPEED_MILLIMETERS_PER_DAY: Final = ( +_DEPRECATED_SPEED_MILLIMETERS_PER_DAY: Final = DeprecatedConstantEnum( UnitOfVolumetricFlux.MILLIMETERS_PER_DAY, "2025.1", ) """Deprecated: please use UnitOfVolumetricFlux.MILLIMETERS_PER_DAY""" -_DEPRECATED_SPEED_INCHES_PER_DAY: Final = ( +_DEPRECATED_SPEED_INCHES_PER_DAY: Final = DeprecatedConstantEnum( UnitOfVolumetricFlux.INCHES_PER_DAY, "2025.1", ) """Deprecated: please use UnitOfVolumetricFlux.INCHES_PER_DAY""" -_DEPRECATED_SPEED_INCHES_PER_HOUR: Final = ( +_DEPRECATED_SPEED_INCHES_PER_HOUR: Final = DeprecatedConstantEnum( UnitOfVolumetricFlux.INCHES_PER_HOUR, "2025.1", ) @@ -1288,47 +1288,87 @@ class UnitOfInformation(StrEnum): YOBIBYTES = "YiB" -_DEPRECATED_DATA_BITS: Final = (UnitOfInformation.BITS, "2025.1") +_DEPRECATED_DATA_BITS: Final = DeprecatedConstantEnum(UnitOfInformation.BITS, "2025.1") """Deprecated: please use UnitOfInformation.BITS""" -_DEPRECATED_DATA_KILOBITS: Final = (UnitOfInformation.KILOBITS, "2025.1") +_DEPRECATED_DATA_KILOBITS: Final = DeprecatedConstantEnum( + UnitOfInformation.KILOBITS, "2025.1" +) """Deprecated: please use UnitOfInformation.KILOBITS""" -_DEPRECATED_DATA_MEGABITS: Final = (UnitOfInformation.MEGABITS, "2025.1") +_DEPRECATED_DATA_MEGABITS: Final = DeprecatedConstantEnum( + UnitOfInformation.MEGABITS, "2025.1" +) """Deprecated: please use UnitOfInformation.MEGABITS""" -_DEPRECATED_DATA_GIGABITS: Final = (UnitOfInformation.GIGABITS, "2025.1") +_DEPRECATED_DATA_GIGABITS: Final = DeprecatedConstantEnum( + UnitOfInformation.GIGABITS, "2025.1" +) """Deprecated: please use UnitOfInformation.GIGABITS""" -_DEPRECATED_DATA_BYTES: Final = (UnitOfInformation.BYTES, "2025.1") +_DEPRECATED_DATA_BYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.BYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.BYTES""" -_DEPRECATED_DATA_KILOBYTES: Final = (UnitOfInformation.KILOBYTES, "2025.1") +_DEPRECATED_DATA_KILOBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.KILOBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.KILOBYTES""" -_DEPRECATED_DATA_MEGABYTES: Final = (UnitOfInformation.MEGABYTES, "2025.1") +_DEPRECATED_DATA_MEGABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.MEGABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.MEGABYTES""" -_DEPRECATED_DATA_GIGABYTES: Final = (UnitOfInformation.GIGABYTES, "2025.1") +_DEPRECATED_DATA_GIGABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.GIGABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.GIGABYTES""" -_DEPRECATED_DATA_TERABYTES: Final = (UnitOfInformation.TERABYTES, "2025.1") +_DEPRECATED_DATA_TERABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.TERABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.TERABYTES""" -_DEPRECATED_DATA_PETABYTES: Final = (UnitOfInformation.PETABYTES, "2025.1") +_DEPRECATED_DATA_PETABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.PETABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.PETABYTES""" -_DEPRECATED_DATA_EXABYTES: Final = (UnitOfInformation.EXABYTES, "2025.1") +_DEPRECATED_DATA_EXABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.EXABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.EXABYTES""" -_DEPRECATED_DATA_ZETTABYTES: Final = (UnitOfInformation.ZETTABYTES, "2025.1") +_DEPRECATED_DATA_ZETTABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.ZETTABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.ZETTABYTES""" -_DEPRECATED_DATA_YOTTABYTES: Final = (UnitOfInformation.YOTTABYTES, "2025.1") +_DEPRECATED_DATA_YOTTABYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.YOTTABYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.YOTTABYTES""" -_DEPRECATED_DATA_KIBIBYTES: Final = (UnitOfInformation.KIBIBYTES, "2025.1") +_DEPRECATED_DATA_KIBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.KIBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.KIBIBYTES""" -_DEPRECATED_DATA_MEBIBYTES: Final = (UnitOfInformation.MEBIBYTES, "2025.1") +_DEPRECATED_DATA_MEBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.MEBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.MEBIBYTES""" -_DEPRECATED_DATA_GIBIBYTES: Final = (UnitOfInformation.GIBIBYTES, "2025.1") +_DEPRECATED_DATA_GIBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.GIBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.GIBIBYTES""" -_DEPRECATED_DATA_TEBIBYTES: Final = (UnitOfInformation.TEBIBYTES, "2025.1") +_DEPRECATED_DATA_TEBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.TEBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.TEBIBYTES""" -_DEPRECATED_DATA_PEBIBYTES: Final = (UnitOfInformation.PEBIBYTES, "2025.1") +_DEPRECATED_DATA_PEBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.PEBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.PEBIBYTES""" -_DEPRECATED_DATA_EXBIBYTES: Final = (UnitOfInformation.EXBIBYTES, "2025.1") +_DEPRECATED_DATA_EXBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.EXBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.EXBIBYTES""" -_DEPRECATED_DATA_ZEBIBYTES: Final = (UnitOfInformation.ZEBIBYTES, "2025.1") +_DEPRECATED_DATA_ZEBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.ZEBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.ZEBIBYTES""" -_DEPRECATED_DATA_YOBIBYTES: Final = (UnitOfInformation.YOBIBYTES, "2025.1") +_DEPRECATED_DATA_YOBIBYTES: Final = DeprecatedConstantEnum( + UnitOfInformation.YOBIBYTES, "2025.1" +) """Deprecated: please use UnitOfInformation.YOBIBYTES""" @@ -1349,57 +1389,57 @@ class UnitOfDataRate(StrEnum): GIBIBYTES_PER_SECOND = "GiB/s" -_DEPRECATED_DATA_RATE_BITS_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_BITS_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.BITS_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.BITS_PER_SECOND""" -_DEPRECATED_DATA_RATE_KILOBITS_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_KILOBITS_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.KILOBITS_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.KILOBITS_PER_SECOND""" -_DEPRECATED_DATA_RATE_MEGABITS_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_MEGABITS_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.MEGABITS_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.MEGABITS_PER_SECOND""" -_DEPRECATED_DATA_RATE_GIGABITS_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_GIGABITS_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.GIGABITS_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.GIGABITS_PER_SECOND""" -_DEPRECATED_DATA_RATE_BYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_BYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.BYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.BYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_KILOBYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_KILOBYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.KILOBYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.KILOBYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_MEGABYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_MEGABYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.MEGABYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.MEGABYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_GIGABYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_GIGABYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.GIGABYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.GIGABYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_KIBIBYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_KIBIBYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.KIBIBYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.KIBIBYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_MEBIBYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_MEBIBYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.MEBIBYTES_PER_SECOND, "2025.1", ) """Deprecated: please use UnitOfDataRate.MEBIBYTES_PER_SECOND""" -_DEPRECATED_DATA_RATE_GIBIBYTES_PER_SECOND: Final = ( +_DEPRECATED_DATA_RATE_GIBIBYTES_PER_SECOND: Final = DeprecatedConstantEnum( UnitOfDataRate.GIBIBYTES_PER_SECOND, "2025.1", ) @@ -1540,8 +1580,12 @@ class EntityCategory(StrEnum): # ENTITY_CATEGOR* below are deprecated as of 2021.12 # use the EntityCategory enum instead. -_DEPRECATED_ENTITY_CATEGORY_CONFIG: Final = (EntityCategory.CONFIG, "2025.1") -_DEPRECATED_ENTITY_CATEGORY_DIAGNOSTIC: Final = (EntityCategory.DIAGNOSTIC, "2025.1") +_DEPRECATED_ENTITY_CATEGORY_CONFIG: Final = DeprecatedConstantEnum( + EntityCategory.CONFIG, "2025.1" +) +_DEPRECATED_ENTITY_CATEGORY_DIAGNOSTIC: Final = DeprecatedConstantEnum( + EntityCategory.DIAGNOSTIC, "2025.1" +) ENTITY_CATEGORIES: Final[list[str]] = [cls.value for cls in EntityCategory] # The ID of the Home Assistant Media Player Cast App @@ -1558,3 +1602,10 @@ class EntityCategory(StrEnum): FORMAT_DATE: Final = "%Y-%m-%d" FORMAT_TIME: Final = "%H:%M:%S" FORMAT_DATETIME: Final = f"{FORMAT_DATE} {FORMAT_TIME}" + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/core.py b/homeassistant/core.py index 51cb3d4e496d5..e843481f79daf 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -81,6 +81,12 @@ ServiceNotFound, Unauthorized, ) +from .helpers.deprecation import ( + DeprecatedConstantEnum, + all_with_deprecated_constants, + check_if_deprecated_constant, + dir_with_deprecated_constants, +) from .helpers.json import json_dumps from .util import dt as dt_util, location from .util.async_ import ( @@ -147,41 +153,11 @@ class ConfigSource(enum.StrEnum): # SOURCE_* are deprecated as of Home Assistant 2022.2, use ConfigSource instead -_DEPRECATED_SOURCE_DISCOVERED = (ConfigSource.DISCOVERED, "2025.1") -_DEPRECATED_SOURCE_STORAGE = (ConfigSource.STORAGE, "2025.1") -_DEPRECATED_SOURCE_YAML = (ConfigSource.YAML, "2025.1") - - -# Can be removed if no deprecated constant are in this module anymore -def __getattr__(name: str) -> Any: - """Check if the not found name is a deprecated constant. - - If it is, print a deprecation warning and return the value of the constant. - Otherwise raise AttributeError. - """ - module_globals = globals() - if f"_DEPRECATED_{name}" not in module_globals: - raise AttributeError(f"Module {__name__} has no attribute {name!r}") - - # Avoid circular import - from .helpers.deprecation import ( # pylint: disable=import-outside-toplevel - check_if_deprecated_constant, - ) - - return check_if_deprecated_constant(name, module_globals) - - -# Can be removed if no deprecated constant are in this module anymore -def __dir__() -> list[str]: - """Return dir() with deprecated constants.""" - # Copied method from homeassistant.helpers.deprecattion#dir_with_deprecated_constants to avoid import cycle - module_globals = globals() - - return list(module_globals) + [ - name.removeprefix("_DEPRECATED_") - for name in module_globals - if name.startswith("_DEPRECATED_") - ] +_DEPRECATED_SOURCE_DISCOVERED = DeprecatedConstantEnum( + ConfigSource.DISCOVERED, "2025.1" +) +_DEPRECATED_SOURCE_STORAGE = DeprecatedConstantEnum(ConfigSource.STORAGE, "2025.1") +_DEPRECATED_SOURCE_YAML = DeprecatedConstantEnum(ConfigSource.YAML, "2025.1") # How long to wait until things that run on startup have to finish. @@ -2554,3 +2530,11 @@ async def async_save(self, data: dict[str, Any]) -> None: if self._original_unit_system: data["unit_system"] = self._original_unit_system return await super().async_save(data) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = functools.partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = functools.partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index 5c9c0ff1ce4d7..63ba565582a8b 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -17,6 +17,7 @@ from .exceptions import HomeAssistantError from .helpers.deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -59,10 +60,6 @@ class FlowResultType(StrEnum): ) _DEPRECATED_RESULT_TYPE_MENU = DeprecatedConstantEnum(FlowResultType.MENU, "2025.1") -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - # Event that is fired when a flow is progressed via external or progress source. EVENT_DATA_ENTRY_FLOW_PROGRESSED = "data_entry_flow_progressed" @@ -700,3 +697,11 @@ def _create_abort_data( reason=reason, description_placeholders=description_placeholders, ) + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/helpers/deprecation.py b/homeassistant/helpers/deprecation.py index efd0363732a80..18a42ce9bcf1d 100644 --- a/homeassistant/helpers/deprecation.py +++ b/homeassistant/helpers/deprecation.py @@ -9,12 +9,6 @@ import logging from typing import Any, NamedTuple, ParamSpec, TypeVar -from homeassistant.core import HomeAssistant, async_get_hass -from homeassistant.exceptions import HomeAssistantError -from homeassistant.loader import async_suggest_report_issue - -from .frame import MissingIntegrationFrame, get_integration_frame - _ObjectT = TypeVar("_ObjectT", bound=object) _R = TypeVar("_R") _P = ParamSpec("_P") @@ -175,6 +169,13 @@ def _print_deprecation_warning_internal( *, log_when_no_integration_is_found: bool, ) -> None: + # pylint: disable=import-outside-toplevel + from homeassistant.core import HomeAssistant, async_get_hass + from homeassistant.exceptions import HomeAssistantError + from homeassistant.loader import async_suggest_report_issue + + from .frame import MissingIntegrationFrame, get_integration_frame + logger = logging.getLogger(module_name) if breaks_in_ha_version: breaks_in = f" which will be removed in HA Core {breaks_in_ha_version}" @@ -265,18 +266,6 @@ def check_if_deprecated_constant(name: str, module_globals: dict[str, Any]) -> A f"{deprecated_const.enum.__class__.__name__}.{deprecated_const.enum.name}" ) breaks_in_ha_version = deprecated_const.breaks_in_ha_version - elif isinstance(deprecated_const, tuple): - # Use DeprecatedConstant and DeprecatedConstant instead, where possible - # Used to avoid import cycles. - if len(deprecated_const) == 3: - value = deprecated_const[0] - replacement = deprecated_const[1] - breaks_in_ha_version = deprecated_const[2] - elif len(deprecated_const) == 2 and isinstance(deprecated_const[0], Enum): - enum = deprecated_const[0] - value = enum.value - replacement = f"{enum.__class__.__name__}.{enum.name}" - breaks_in_ha_version = deprecated_const[1] if value is None or replacement is None: msg = ( @@ -303,10 +292,22 @@ def check_if_deprecated_constant(name: str, module_globals: dict[str, Any]) -> A return value -def dir_with_deprecated_constants(module_globals: dict[str, Any]) -> list[str]: +def dir_with_deprecated_constants(module_globals_keys: list[str]) -> list[str]: """Return dir() with deprecated constants.""" - return list(module_globals) + [ + return module_globals_keys + [ + name.removeprefix(_PREFIX_DEPRECATED) + for name in module_globals_keys + if name.startswith(_PREFIX_DEPRECATED) + ] + + +def all_with_deprecated_constants(module_globals: dict[str, Any]) -> list[str]: + """Generate a list for __all___ with deprecated constants.""" + # Iterate over a copy in case the globals dict is mutated by another thread + # while we loop over it. + module_globals_keys = list(module_globals) + return [itm for itm in module_globals_keys if not itm.startswith("_")] + [ name.removeprefix(_PREFIX_DEPRECATED) - for name in module_globals + for name in module_globals_keys if name.startswith(_PREFIX_DEPRECATED) ] diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index bd509cb47ec24..cfe3b78ebab3f 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -24,6 +24,7 @@ from .debounce import Debouncer from .deprecation import ( DeprecatedConstantEnum, + all_with_deprecated_constants, check_if_deprecated_constant, dir_with_deprecated_constants, ) @@ -75,10 +76,6 @@ class DeviceEntryDisabler(StrEnum): ) _DEPRECATED_DISABLED_USER = DeprecatedConstantEnum(DeviceEntryDisabler.USER, "2025.1") -# Both can be removed if no deprecated constant are in this module anymore -__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) -__dir__ = partial(dir_with_deprecated_constants, module_globals=globals()) - class DeviceInfo(TypedDict, total=False): """Entity device information for device registry.""" @@ -1113,3 +1110,11 @@ def _normalize_connections(connections: set[tuple[str, str]]) -> set[tuple[str, (key, format_mac(value)) if key == CONNECTION_NETWORK_MAC else (key, value) for key, value in connections } + + +# These can be removed if no deprecated constant are in this module anymore +__getattr__ = partial(check_if_deprecated_constant, module_globals=globals()) +__dir__ = partial( + dir_with_deprecated_constants, module_globals_keys=[*globals().keys()] +) +__all__ = all_with_deprecated_constants(globals()) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 3c3c8474e67a2..743d3675a3b1c 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -292,7 +292,7 @@ def __new__( Pop cached_properties and store it in the namespace. """ namespace["_CachedProperties__cached_properties"] = cached_properties or set() - return super().__new__(mcs, name, bases, namespace) + return super().__new__(mcs, name, bases, namespace, **kwargs) def __init__( cls, diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 0f069a0e0b52d..655f46a88383a 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -24,11 +24,11 @@ dbus-fast==2.21.0 fnv-hash-fast==0.5.0 ha-av==10.1.1 ha-ffmpeg==3.1.0 -habluetooth==2.0.1 +habluetooth==2.0.2 hass-nabucasa==0.75.1 hassil==1.5.1 home-assistant-bluetooth==1.11.0 -home-assistant-frontend==20240103.3 +home-assistant-frontend==20240104.0 home-assistant-intents==2024.1.2 httpx==0.26.0 ifaddr==0.2.0 diff --git a/mypy.ini b/mypy.ini index e19c6c6fa925d..e4546526722ec 100644 --- a/mypy.ini +++ b/mypy.ini @@ -250,6 +250,16 @@ disallow_untyped_defs = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.airthings_ble.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + [mypy-homeassistant.components.airvisual.*] check_untyped_defs = true disallow_incomplete_defs = true diff --git a/pyproject.toml b/pyproject.toml index ec313a5bcf6de..3bec11ced3bbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2024.1.0" +version = "2024.1.1" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" @@ -176,7 +176,8 @@ disable = [ "duplicate-bases", # PLE0241 "format-needs-mapping", # F502 "function-redefined", # F811 - "invalid-all-format", # PLE0605 + # Needed because ruff does not understand type of __all__ generated by a function + # "invalid-all-format", # PLE0605 "invalid-all-object", # PLE0604 "invalid-character-backspace", # PLE2510 "invalid-character-esc", # PLE2513 @@ -673,6 +674,9 @@ ignore = [ "COM819", "ISC001", "ISC002", + + # Disabled because ruff does not understand type of __all__ generated by a function + "PLE0605", ] [tool.ruff.flake8-import-conventions.extend-aliases] diff --git a/requirements_all.txt b/requirements_all.txt index 46b89f491a99d..012c601b78518 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -257,7 +257,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==3.1.1 +aiohomekit==3.1.2 # homeassistant.components.http aiohttp-fast-url-dispatcher==0.3.0 @@ -716,7 +716,7 @@ dovado==0.4.1 dremel3dpy==2.1.1 # homeassistant.components.drop_connect -dropmqttapi==1.0.1 +dropmqttapi==1.0.2 # homeassistant.components.dsmr dsmr-parser==1.3.1 @@ -998,7 +998,7 @@ ha-philipsjs==3.1.1 habitipy==0.2.0 # homeassistant.components.bluetooth -habluetooth==2.0.1 +habluetooth==2.0.2 # homeassistant.components.cloud hass-nabucasa==0.75.1 @@ -1038,7 +1038,7 @@ hole==0.8.0 holidays==0.39 # homeassistant.components.frontend -home-assistant-frontend==20240103.3 +home-assistant-frontend==20240104.0 # homeassistant.components.conversation home-assistant-intents==2024.1.2 @@ -1425,7 +1425,7 @@ openhomedevice==2.2.0 opensensemap-api==0.2.0 # homeassistant.components.enigma2 -openwebifpy==4.0.2 +openwebifpy==4.0.4 # homeassistant.components.luci openwrt-luci-rpc==1.1.16 @@ -1443,7 +1443,7 @@ oralb-ble==0.17.6 oru==0.1.11 # homeassistant.components.orvibo -orvibo==1.1.1 +orvibo==1.1.2 # homeassistant.components.ourgroceries ourgroceries==1.5.4 @@ -2241,7 +2241,7 @@ python-smarttub==0.0.36 python-songpal==0.16 # homeassistant.components.tado -python-tado==0.17.0 +python-tado==0.17.3 # homeassistant.components.telegram_bot python-telegram-bot==13.1 @@ -2893,7 +2893,7 @@ zigpy==0.60.4 zm-py==0.5.2 # homeassistant.components.zwave_js -zwave-js-server-python==0.55.2 +zwave-js-server-python==0.55.3 # homeassistant.components.zwave_me zwave-me-ws==0.4.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ee1a9b2ac35fa..96775e057914e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -233,7 +233,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==3.1.1 +aiohomekit==3.1.2 # homeassistant.components.http aiohttp-fast-url-dispatcher==0.3.0 @@ -585,7 +585,7 @@ discovery30303==0.2.1 dremel3dpy==2.1.1 # homeassistant.components.drop_connect -dropmqttapi==1.0.1 +dropmqttapi==1.0.2 # homeassistant.components.dsmr dsmr-parser==1.3.1 @@ -803,7 +803,7 @@ ha-philipsjs==3.1.1 habitipy==0.2.0 # homeassistant.components.bluetooth -habluetooth==2.0.1 +habluetooth==2.0.2 # homeassistant.components.cloud hass-nabucasa==0.75.1 @@ -831,7 +831,7 @@ hole==0.8.0 holidays==0.39 # homeassistant.components.frontend -home-assistant-frontend==20240103.3 +home-assistant-frontend==20240104.0 # homeassistant.components.conversation home-assistant-intents==2024.1.2 @@ -1696,7 +1696,7 @@ python-smarttub==0.0.36 python-songpal==0.16 # homeassistant.components.tado -python-tado==0.17.0 +python-tado==0.17.3 # homeassistant.components.telegram_bot python-telegram-bot==13.1 @@ -2189,7 +2189,7 @@ zigpy-znp==0.12.1 zigpy==0.60.4 # homeassistant.components.zwave_js -zwave-js-server-python==0.55.2 +zwave-js-server-python==0.55.3 # homeassistant.components.zwave_me zwave-me-ws==0.4.3 diff --git a/tests/common.py b/tests/common.py index b07788dc3d73a..85193022e4f9a 100644 --- a/tests/common.py +++ b/tests/common.py @@ -92,7 +92,7 @@ import homeassistant.util.yaml.loader as yaml_loader from tests.testing_config.custom_components.test_constant_deprecation import ( - import_deprecated_costant, + import_deprecated_constant, ) _LOGGER = logging.getLogger(__name__) @@ -1482,6 +1482,7 @@ def import_and_test_deprecated_constant_enum( - Assert value is the same as the replacement - Assert a warning is logged - Assert the deprecated constant is included in the modules.__dir__() + - Assert the deprecated constant is included in the modules.__all__() """ import_and_test_deprecated_constant( caplog, @@ -1507,8 +1508,9 @@ def import_and_test_deprecated_constant( - Assert value is the same as the replacement - Assert a warning is logged - Assert the deprecated constant is included in the modules.__dir__() + - Assert the deprecated constant is included in the modules.__all__() """ - value = import_deprecated_costant(module, constant_name) + value = import_deprecated_constant(module, constant_name) assert value == replacement assert ( module.__name__, @@ -1523,3 +1525,11 @@ def import_and_test_deprecated_constant( # verify deprecated constant is included in dir() assert constant_name in dir(module) + assert constant_name in module.__all__ + + +def help_test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + assert set(module.__all__) == { + itm for itm in module.__dir__() if not itm.startswith("_") + } diff --git a/tests/components/alarm_control_panel/test_init.py b/tests/components/alarm_control_panel/test_init.py index 1e6fce6def625..42a532cbb1a19 100644 --- a/tests/components/alarm_control_panel/test_init.py +++ b/tests/components/alarm_control_panel/test_init.py @@ -6,7 +6,16 @@ from homeassistant.components import alarm_control_panel -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum + + +@pytest.mark.parametrize( + "module", + [alarm_control_panel, alarm_control_panel.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) @pytest.mark.parametrize( diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index 235ca48f095e4..6bb1b89259a61 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -59,6 +59,7 @@ async_capture_events, async_fire_time_changed, async_mock_service, + help_test_all, import_and_test_deprecated_constant, mock_restore_cache, ) @@ -2569,6 +2570,11 @@ async def test_websocket_config( assert msg["error"]["code"] == "not_found" +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(automation) + + @pytest.mark.parametrize( ("constant_name", "replacement"), [ diff --git a/tests/components/binary_sensor/test_init.py b/tests/components/binary_sensor/test_init.py index 014722d94a4f3..6ca189113b9ea 100644 --- a/tests/components/binary_sensor/test_init.py +++ b/tests/components/binary_sensor/test_init.py @@ -14,6 +14,7 @@ MockConfigEntry, MockModule, MockPlatform, + help_test_all, import_and_test_deprecated_constant_enum, mock_config_flow, mock_integration, @@ -197,6 +198,11 @@ async def async_setup_entry_platform( ) +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(binary_sensor) + + @pytest.mark.parametrize( "device_class", list(binary_sensor.BinarySensorDeviceClass), diff --git a/tests/components/bluetooth/test_wrappers.py b/tests/components/bluetooth/test_wrappers.py index cc837f381d491..e3531a574471f 100644 --- a/tests/components/bluetooth/test_wrappers.py +++ b/tests/components/bluetooth/test_wrappers.py @@ -367,6 +367,38 @@ async def connect(self, *args, **kwargs): cancel_hci1() +async def test_passing_subclassed_str_as_address( + hass: HomeAssistant, + two_adapters: None, + enable_bluetooth: None, + install_bleak_catcher, +) -> None: + """Ensure the client wrapper can handle a subclassed str as the address.""" + _, cancel_hci0, cancel_hci1 = _generate_scanners_with_fake_devices(hass) + + class SubclassedStr(str): + pass + + address = SubclassedStr("00:00:00:00:00:01") + client = bleak.BleakClient(address) + + class FakeBleakClient(BaseFakeBleakClient): + """Fake bleak client.""" + + async def connect(self, *args, **kwargs): + """Connect.""" + return True + + with patch( + "habluetooth.wrappers.get_platform_client_backend_type", + return_value=FakeBleakClient, + ): + assert await client.connect() is True + + cancel_hci0() + cancel_hci1() + + async def test_raise_after_shutdown( hass: HomeAssistant, two_adapters: None, diff --git a/tests/components/camera/test_init.py b/tests/components/camera/test_init.py index 0e761f2f43723..f1e3a4fdef5bc 100644 --- a/tests/components/camera/test_init.py +++ b/tests/components/camera/test_init.py @@ -27,7 +27,7 @@ from .common import EMPTY_8_6_JPEG, WEBRTC_ANSWER, mock_turbo_jpeg -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum from tests.typing import ClientSessionGenerator, WebSocketGenerator STREAM_SOURCE = "rtsp://127.0.0.1/stream" @@ -962,6 +962,15 @@ async def test_use_stream_for_stills( assert await resp.read() == b"stream_keyframe_image" +@pytest.mark.parametrize( + "module", + [camera, camera.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize( "enum", list(camera.const.StreamType), diff --git a/tests/components/climate/test_init.py b/tests/components/climate/test_init.py index 8fc82365c23ee..89826c9808661 100644 --- a/tests/components/climate/test_init.py +++ b/tests/components/climate/test_init.py @@ -36,6 +36,7 @@ MockModule, MockPlatform, async_mock_service, + help_test_all, import_and_test_deprecated_constant, import_and_test_deprecated_constant_enum, mock_integration, @@ -157,6 +158,15 @@ def _create_tuples(enum: Enum, constant_prefix: str) -> list[tuple[Enum, str]]: return result +@pytest.mark.parametrize( + "module", + [climate, climate.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize( ("enum", "constant_prefix"), _create_tuples(climate.ClimateEntityFeature, "SUPPORT_") diff --git a/tests/components/cloud/conftest.py b/tests/components/cloud/conftest.py index ef8cb037cdbf7..42852b1520611 100644 --- a/tests/components/cloud/conftest.py +++ b/tests/components/cloud/conftest.py @@ -109,6 +109,7 @@ def mock_is_connected() -> bool: is_connected = PropertyMock(side_effect=mock_is_connected) type(mock_cloud).is_connected = is_connected + type(mock_cloud.iot).connected = is_connected # Properties that we mock as attributes. mock_cloud.expiration_date = utcnow() diff --git a/tests/components/cloud/test_init.py b/tests/components/cloud/test_init.py index e12775d5a4a5f..850f8e12e0208 100644 --- a/tests/components/cloud/test_init.py +++ b/tests/components/cloud/test_init.py @@ -1,12 +1,18 @@ """Test the cloud component.""" +from collections.abc import Callable, Coroutine from typing import Any -from unittest.mock import patch +from unittest.mock import MagicMock, patch from hass_nabucasa import Cloud import pytest from homeassistant.components import cloud -from homeassistant.components.cloud.const import DOMAIN +from homeassistant.components.cloud import ( + CloudNotAvailable, + CloudNotConnected, + async_get_or_create_cloudhook, +) +from homeassistant.components.cloud.const import DOMAIN, PREF_CLOUDHOOKS from homeassistant.components.cloud.prefs import STORAGE_KEY from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import Context, HomeAssistant @@ -214,3 +220,57 @@ async def test_remote_ui_url(hass: HomeAssistant, mock_cloud_fixture) -> None: cl.client.prefs._prefs["remote_domain"] = "example.com" assert cloud.async_remote_ui_url(hass) == "https://example.com" + + +async def test_async_get_or_create_cloudhook( + hass: HomeAssistant, + cloud: MagicMock, + set_cloud_prefs: Callable[[dict[str, Any]], Coroutine[Any, Any, None]], +) -> None: + """Test async_get_or_create_cloudhook.""" + assert await async_setup_component(hass, "cloud", {"cloud": {}}) + await hass.async_block_till_done() + + webhook_id = "mock-webhook-id" + cloudhook_url = "https://cloudhook.nabu.casa/abcdefg" + + with patch( + "homeassistant.components.cloud.async_create_cloudhook", + return_value=cloudhook_url, + ) as async_create_cloudhook_mock: + # create cloudhook as it does not exist + assert (await async_get_or_create_cloudhook(hass, webhook_id)) == cloudhook_url + async_create_cloudhook_mock.assert_called_once_with(hass, webhook_id) + + await set_cloud_prefs( + { + PREF_CLOUDHOOKS: { + webhook_id: { + "webhook_id": webhook_id, + "cloudhook_id": "random-id", + "cloudhook_url": cloudhook_url, + "managed": True, + } + } + } + ) + + async_create_cloudhook_mock.reset_mock() + + # get cloudhook as it exists + assert await async_get_or_create_cloudhook(hass, webhook_id) == cloudhook_url + async_create_cloudhook_mock.assert_not_called() + + # Simulate logged out + cloud.id_token = None + + # Not logged in + with pytest.raises(CloudNotAvailable): + await async_get_or_create_cloudhook(hass, webhook_id) + + # Simulate disconnected + cloud.iot.state = "disconnected" + + # Not connected + with pytest.raises(CloudNotConnected): + await async_get_or_create_cloudhook(hass, webhook_id) diff --git a/tests/components/cover/test_init.py b/tests/components/cover/test_init.py index 1b08658d9839d..480d1ef83aa57 100644 --- a/tests/components/cover/test_init.py +++ b/tests/components/cover/test_init.py @@ -16,7 +16,7 @@ from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum async def test_services(hass: HomeAssistant, enable_custom_integrations: None) -> None: @@ -127,6 +127,11 @@ def _create_tuples(enum: Enum, constant_prefix: str) -> list[tuple[Enum, str]]: return result +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(cover) + + @pytest.mark.parametrize( ("enum", "constant_prefix"), _create_tuples(cover.CoverEntityFeature, "SUPPORT_") diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index 024187a33f6a9..eb8fde8f0e273 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -34,6 +34,7 @@ from tests.common import ( assert_setup_component, async_fire_time_changed, + help_test_all, import_and_test_deprecated_constant_enum, mock_registry, mock_restore_cache, @@ -685,6 +686,15 @@ def test_see_schema_allowing_ios_calls() -> None: ) +@pytest.mark.parametrize( + "module", + [device_tracker, device_tracker.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize(("enum"), list(SourceType)) @pytest.mark.parametrize( "module", diff --git a/tests/components/fan/test_init.py b/tests/components/fan/test_init.py index 828c13b6f167d..1beea47c6fa84 100644 --- a/tests/components/fan/test_init.py +++ b/tests/components/fan/test_init.py @@ -15,7 +15,7 @@ import homeassistant.helpers.entity_registry as er from homeassistant.setup import async_setup_component -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum from tests.testing_config.custom_components.test.fan import MockFan @@ -150,6 +150,11 @@ async def test_preset_mode_validation( assert exc.value.translation_key == "not_valid_preset_mode" +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(fan) + + @pytest.mark.parametrize(("enum"), list(fan.FanEntityFeature)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/components/humidifier/test_init.py b/tests/components/humidifier/test_init.py index 45da5ba750f7f..3ef3fca858996 100644 --- a/tests/components/humidifier/test_init.py +++ b/tests/components/humidifier/test_init.py @@ -7,12 +7,13 @@ from homeassistant.components import humidifier from homeassistant.components.humidifier import ( + ATTR_MODE, HumidifierEntity, HumidifierEntityFeature, ) from homeassistant.core import HomeAssistant -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum class MockHumidifierEntity(HumidifierEntity): @@ -53,6 +54,15 @@ def _create_tuples(enum: Enum, constant_prefix: str) -> list[tuple[Enum, str]]: return result +@pytest.mark.parametrize( + "module", + [humidifier, humidifier.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize( ("enum", "constant_prefix"), _create_tuples(humidifier.HumidifierEntityFeature, "SUPPORT_") @@ -75,6 +85,8 @@ def test_deprecated_supported_features_ints(caplog: pytest.LogCaptureFixture) -> """Test deprecated supported features ints.""" class MockHumidifierEntity(HumidifierEntity): + _attr_mode = "mode1" + @property def supported_features(self) -> int: """Return supported features.""" @@ -89,3 +101,5 @@ def supported_features(self) -> int: caplog.clear() assert entity.supported_features_compat is HumidifierEntityFeature(1) assert "is using deprecated supported features values" not in caplog.text + + assert entity.state_attributes[ATTR_MODE] == "mode1" diff --git a/tests/components/lock/test_init.py b/tests/components/lock/test_init.py index 854b89fd1d831..7ebb5bf3027b8 100644 --- a/tests/components/lock/test_init.py +++ b/tests/components/lock/test_init.py @@ -28,7 +28,7 @@ from .conftest import MockLock -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum async def help_test_async_lock_service( @@ -371,6 +371,11 @@ async def test_lock_with_illegal_default_code( assert exc.value.translation_key == "add_default_code" +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(lock) + + @pytest.mark.parametrize(("enum"), list(LockEntityFeature)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/components/mobile_app/test_init.py b/tests/components/mobile_app/test_init.py index d504703c22233..6a365e84fb0f1 100644 --- a/tests/components/mobile_app/test_init.py +++ b/tests/components/mobile_app/test_init.py @@ -88,15 +88,17 @@ async def _test_create_cloud_hook( ), patch( "homeassistant.components.cloud.async_is_connected", return_value=True ), patch( - "homeassistant.components.cloud.async_create_cloudhook", autospec=True - ) as mock_create_cloudhook: + "homeassistant.components.cloud.async_get_or_create_cloudhook", autospec=True + ) as mock_async_get_or_create_cloudhook: cloud_hook = "https://hook-url" - mock_create_cloudhook.return_value = cloud_hook + mock_async_get_or_create_cloudhook.return_value = cloud_hook assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED - await additional_steps(config_entry, mock_create_cloudhook, cloud_hook) + await additional_steps( + config_entry, mock_async_get_or_create_cloudhook, cloud_hook + ) async def test_create_cloud_hook_on_setup( diff --git a/tests/components/number/test_const.py b/tests/components/number/test_const.py index e4b47e17e6ede..13d94e2eeaf55 100644 --- a/tests/components/number/test_const.py +++ b/tests/components/number/test_const.py @@ -4,7 +4,12 @@ from homeassistant.components.number import const -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum + + +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(const) @pytest.mark.parametrize(("enum"), list(const.NumberMode)) diff --git a/tests/components/remote/test_init.py b/tests/components/remote/test_init.py index a75ff85848362..be4a4843097bd 100644 --- a/tests/components/remote/test_init.py +++ b/tests/components/remote/test_init.py @@ -22,7 +22,11 @@ ) from homeassistant.core import HomeAssistant -from tests.common import async_mock_service, import_and_test_deprecated_constant_enum +from tests.common import ( + async_mock_service, + help_test_all, + import_and_test_deprecated_constant_enum, +) TEST_PLATFORM = {DOMAIN: {CONF_PLATFORM: "test"}} SERVICE_SEND_COMMAND = "send_command" @@ -143,6 +147,11 @@ async def test_delete_command(hass: HomeAssistant) -> None: assert call.data[ATTR_ENTITY_ID] == ENTITY_ID +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(remote) + + @pytest.mark.parametrize(("enum"), list(remote.RemoteEntityFeature)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index 829bb5af8279e..522afe3b992e5 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -52,6 +52,7 @@ MockModule, MockPlatform, async_mock_restore_state_shutdown_restart, + help_test_all, import_and_test_deprecated_constant_enum, mock_config_flow, mock_integration, @@ -2524,6 +2525,15 @@ async def test_entity_category_config_raises_error( assert not hass.states.get("sensor.test") +@pytest.mark.parametrize( + "module", + [sensor, sensor.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize(("enum"), list(sensor.SensorStateClass)) @pytest.mark.parametrize(("module"), [sensor, sensor.const]) def test_deprecated_constants( diff --git a/tests/components/siren/test_init.py b/tests/components/siren/test_init.py index abc5b0fac38b8..1cf44d16ea001 100644 --- a/tests/components/siren/test_init.py +++ b/tests/components/siren/test_init.py @@ -13,7 +13,7 @@ from homeassistant.components.siren.const import SirenEntityFeature from homeassistant.core import HomeAssistant -from tests.common import import_and_test_deprecated_constant_enum +from tests.common import help_test_all, import_and_test_deprecated_constant_enum class MockSirenEntity(SirenEntity): @@ -110,6 +110,15 @@ async def test_missing_tones_dict(hass: HomeAssistant) -> None: process_turn_on_params(siren, {"tone": 3}) +@pytest.mark.parametrize( + "module", + [siren, siren.const], +) +def test_all(module: ModuleType) -> None: + """Test module.__all__ is correctly set.""" + help_test_all(module) + + @pytest.mark.parametrize(("enum"), list(SirenEntityFeature)) @pytest.mark.parametrize(("module"), [siren, siren.const]) def test_deprecated_constants( diff --git a/tests/components/switch/test_init.py b/tests/components/switch/test_init.py index 7a43e0bf50ef8..deb7acb512a94 100644 --- a/tests/components/switch/test_init.py +++ b/tests/components/switch/test_init.py @@ -9,7 +9,11 @@ from . import common -from tests.common import MockUser, import_and_test_deprecated_constant_enum +from tests.common import ( + MockUser, + help_test_all, + import_and_test_deprecated_constant_enum, +) @pytest.fixture(autouse=True) @@ -82,6 +86,11 @@ async def test_switch_context( assert state2.context.user_id == hass_admin_user.id +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(switch) + + @pytest.mark.parametrize(("enum"), list(switch.SwitchDeviceClass)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/components/update/test_init.py b/tests/components/update/test_init.py index 92e63af4b6f9a..67661d6936efa 100644 --- a/tests/components/update/test_init.py +++ b/tests/components/update/test_init.py @@ -885,3 +885,75 @@ def supported_features(self) -> int: caplog.clear() assert entity.supported_features_compat is UpdateEntityFeature(1) assert "is using deprecated supported features values" not in caplog.text + + +async def test_deprecated_supported_features_ints_with_service_call( + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test deprecated supported features ints with install service.""" + + async def async_setup_entry_init( + hass: HomeAssistant, config_entry: ConfigEntry + ) -> bool: + """Set up test config entry.""" + await hass.config_entries.async_forward_entry_setup(config_entry, DOMAIN) + return True + + mock_platform(hass, f"{TEST_DOMAIN}.config_flow") + mock_integration( + hass, + MockModule( + TEST_DOMAIN, + async_setup_entry=async_setup_entry_init, + ), + ) + + class MockUpdateEntity(UpdateEntity): + _attr_supported_features = 1 | 2 + + def install(self, version: str | None = None, backup: bool = False) -> None: + """Install an update.""" + + entity = MockUpdateEntity() + entity.entity_id = ( + "update.test_deprecated_supported_features_ints_with_service_call" + ) + + async def async_setup_entry_platform( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, + ) -> None: + """Set up test update platform via config entry.""" + async_add_entities([entity]) + + mock_platform( + hass, + f"{TEST_DOMAIN}.{DOMAIN}", + MockPlatform(async_setup_entry=async_setup_entry_platform), + ) + + config_entry = MockConfigEntry(domain=TEST_DOMAIN) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert "is using deprecated supported features values" in caplog.text + + assert isinstance(entity.supported_features, int) + + with pytest.raises( + HomeAssistantError, + match="Backup is not supported for update.test_deprecated_supported_features_ints_with_service_call", + ): + await hass.services.async_call( + DOMAIN, + SERVICE_INSTALL, + { + ATTR_VERSION: "0.9.9", + ATTR_BACKUP: True, + ATTR_ENTITY_ID: "update.test_deprecated_supported_features_ints_with_service_call", + }, + blocking=True, + ) diff --git a/tests/components/water_heater/test_init.py b/tests/components/water_heater/test_init.py index 0d33f3a9e936a..b81ef3694521b 100644 --- a/tests/components/water_heater/test_init.py +++ b/tests/components/water_heater/test_init.py @@ -8,13 +8,20 @@ from homeassistant.components import water_heater from homeassistant.components.water_heater import ( + ATTR_OPERATION_LIST, + ATTR_OPERATION_MODE, SET_TEMPERATURE_SCHEMA, WaterHeaterEntity, WaterHeaterEntityFeature, ) +from homeassistant.const import UnitOfTemperature from homeassistant.core import HomeAssistant -from tests.common import async_mock_service, import_and_test_deprecated_constant_enum +from tests.common import ( + async_mock_service, + help_test_all, + import_and_test_deprecated_constant_enum, +) async def test_set_temp_schema_no_req( @@ -99,6 +106,11 @@ async def test_sync_turn_off(hass: HomeAssistant) -> None: assert water_heater.async_turn_off.call_count == 1 +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(water_heater) + + @pytest.mark.parametrize( ("enum"), [ @@ -117,21 +129,26 @@ def test_deprecated_constants( ) -def test_deprecated_supported_features_ints(caplog: pytest.LogCaptureFixture) -> None: +def test_deprecated_supported_features_ints( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: """Test deprecated supported features ints.""" class MockWaterHeaterEntity(WaterHeaterEntity): - @property - def supported_features(self) -> int: - """Return supported features.""" - return 1 + _attr_operation_list = ["mode1", "mode2"] + _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_current_operation = "mode1" + _attr_supported_features = WaterHeaterEntityFeature.OPERATION_MODE.value entity = MockWaterHeaterEntity() - assert entity.supported_features_compat is WaterHeaterEntityFeature(1) + entity.hass = hass + assert entity.supported_features_compat is WaterHeaterEntityFeature(2) assert "MockWaterHeaterEntity" in caplog.text assert "is using deprecated supported features values" in caplog.text assert "Instead it should use" in caplog.text - assert "WaterHeaterEntityFeature.TARGET_TEMPERATURE" in caplog.text + assert "WaterHeaterEntityFeature.OPERATION_MODE" in caplog.text caplog.clear() - assert entity.supported_features_compat is WaterHeaterEntityFeature(1) + assert entity.supported_features_compat is WaterHeaterEntityFeature(2) assert "is using deprecated supported features values" not in caplog.text + assert entity.state_attributes[ATTR_OPERATION_MODE] == "mode1" + assert entity.capability_attributes[ATTR_OPERATION_LIST] == ["mode1", "mode2"] diff --git a/tests/components/zwave_js/test_events.py b/tests/components/zwave_js/test_events.py index 4fbaa97f118e0..1e91b9338fad6 100644 --- a/tests/components/zwave_js/test_events.py +++ b/tests/components/zwave_js/test_events.py @@ -348,7 +348,11 @@ async def test_power_level_notification( async def test_unknown_notification( - hass: HomeAssistant, hank_binary_switch, integration, client + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, + hank_binary_switch, + integration, + client, ) -> None: """Test behavior of unknown notification type events.""" # just pick a random node to fake the notification event @@ -358,8 +362,9 @@ async def test_unknown_notification( # by the lib. We will use a class that is guaranteed not to be recognized notification_obj = AsyncMock() notification_obj.node = node - with pytest.raises(TypeError): - node.emit("notification", {"notification": notification_obj}) + node.emit("notification", {"notification": notification_obj}) + + assert f"Unhandled notification type: {notification_obj}" in caplog.text notification_events = async_capture_events(hass, "zwave_js_notification") diff --git a/tests/helpers/test_deprecation.py b/tests/helpers/test_deprecation.py index bd3546afb124a..25b37e2073f2a 100644 --- a/tests/helpers/test_deprecation.py +++ b/tests/helpers/test_deprecation.py @@ -299,22 +299,6 @@ def _get_value(obj: DeprecatedConstant | DeprecatedConstantEnum | tuple) -> Any: DeprecatedConstantEnum(TestDeprecatedConstantEnum.TEST, "2099.1"), " which will be removed in HA Core 2099.1. Use TestDeprecatedConstantEnum.TEST instead", ), - ( - ("value", "NEW_CONSTANT", None), - ". Use NEW_CONSTANT instead", - ), - ( - (1, "NEW_CONSTANT", "2099.1"), - " which will be removed in HA Core 2099.1. Use NEW_CONSTANT instead", - ), - ( - (TestDeprecatedConstantEnum.TEST, None), - ". Use TestDeprecatedConstantEnum.TEST instead", - ), - ( - (TestDeprecatedConstantEnum.TEST, "2099.1"), - " which will be removed in HA Core 2099.1. Use TestDeprecatedConstantEnum.TEST instead", - ), ], ) @pytest.mark.parametrize( @@ -391,22 +375,6 @@ def test_check_if_deprecated_constant( DeprecatedConstantEnum(TestDeprecatedConstantEnum.TEST, "2099.1"), " which will be removed in HA Core 2099.1. Use TestDeprecatedConstantEnum.TEST instead", ), - ( - ("value", "NEW_CONSTANT", None), - ". Use NEW_CONSTANT instead", - ), - ( - (1, "NEW_CONSTANT", "2099.1"), - " which will be removed in HA Core 2099.1. Use NEW_CONSTANT instead", - ), - ( - (TestDeprecatedConstantEnum.TEST, None), - ". Use TestDeprecatedConstantEnum.TEST instead", - ), - ( - (TestDeprecatedConstantEnum.TEST, "2099.1"), - " which will be removed in HA Core 2099.1. Use TestDeprecatedConstantEnum.TEST instead", - ), ], ) @pytest.mark.parametrize( @@ -461,7 +429,7 @@ def test_test_check_if_deprecated_constant_invalid( @pytest.mark.parametrize( - ("module_global", "expected"), + ("module_globals", "expected"), [ ({"CONSTANT": 1}, ["CONSTANT"]), ({"_DEPRECATED_CONSTANT": 1}, ["_DEPRECATED_CONSTANT", "CONSTANT"]), @@ -472,7 +440,7 @@ def test_test_check_if_deprecated_constant_invalid( ], ) def test_dir_with_deprecated_constants( - module_global: dict[str, Any], expected: list[str] + module_globals: dict[str, Any], expected: list[str] ) -> None: """Test dir() with deprecated constants.""" - assert dir_with_deprecated_constants(module_global) == expected + assert dir_with_deprecated_constants([*module_globals.keys()]) == expected diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py index 43540a52f7dab..240afa2cbab8b 100644 --- a/tests/helpers/test_device_registry.py +++ b/tests/helpers/test_device_registry.py @@ -20,6 +20,7 @@ from tests.common import ( MockConfigEntry, flush_store, + help_test_all, import_and_test_deprecated_constant_enum, ) @@ -2018,6 +2019,11 @@ async def test_loading_invalid_configuration_url_from_storage( assert entry.configuration_url == "invalid" +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(dr) + + @pytest.mark.parametrize(("enum"), list(dr.DeviceEntryDisabler)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/test_const.py b/tests/test_const.py index fedf35ae6d1b8..4b9be4f27f1f6 100644 --- a/tests/test_const.py +++ b/tests/test_const.py @@ -9,6 +9,7 @@ from homeassistant.components import sensor from tests.common import ( + help_test_all, import_and_test_deprecated_constant, import_and_test_deprecated_constant_enum, ) @@ -23,6 +24,11 @@ def _create_tuples( return result +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(const) + + @pytest.mark.parametrize( ("enum", "constant_prefix"), _create_tuples(const.EntityCategory, "ENTITY_CATEGORY_") diff --git a/tests/test_core.py b/tests/test_core.py index 90b87068a5d58..bbd2715124392 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -61,6 +61,7 @@ from .common import ( async_capture_events, async_mock_service, + help_test_all, import_and_test_deprecated_constant_enum, ) @@ -2630,6 +2631,11 @@ async def shutdown_func() -> None: assert not evt.is_set() +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(ha) + + @pytest.mark.parametrize( ("enum"), [ diff --git a/tests/test_data_entry_flow.py b/tests/test_data_entry_flow.py index eb507febe8a1b..602b21c15bc40 100644 --- a/tests/test_data_entry_flow.py +++ b/tests/test_data_entry_flow.py @@ -10,7 +10,11 @@ from homeassistant.core import HomeAssistant from homeassistant.util.decorator import Registry -from .common import async_capture_events, import_and_test_deprecated_constant_enum +from .common import ( + async_capture_events, + help_test_all, + import_and_test_deprecated_constant_enum, +) @pytest.fixture @@ -804,6 +808,11 @@ async def async_step_second(self, user_input=None): assert len(manager.async_progress()) == 0 +def test_all() -> None: + """Test module.__all__ is correctly set.""" + help_test_all(data_entry_flow) + + @pytest.mark.parametrize(("enum"), list(data_entry_flow.FlowResultType)) def test_deprecated_constants( caplog: pytest.LogCaptureFixture, diff --git a/tests/testing_config/custom_components/test_constant_deprecation/__init__.py b/tests/testing_config/custom_components/test_constant_deprecation/__init__.py index 4367cbed7b1af..b061b9c35fc0b 100644 --- a/tests/testing_config/custom_components/test_constant_deprecation/__init__.py +++ b/tests/testing_config/custom_components/test_constant_deprecation/__init__.py @@ -4,6 +4,6 @@ from typing import Any -def import_deprecated_costant(module: ModuleType, constant_name: str) -> Any: +def import_deprecated_constant(module: ModuleType, constant_name: str) -> Any: """Import and return deprecated constant.""" return getattr(module, constant_name)