Skip to content

Commit

Permalink
2024.12.1 (#132509)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenck authored Dec 6, 2024
2 parents 2b40844 + 4884891 commit cf53a97
Show file tree
Hide file tree
Showing 40 changed files with 204 additions and 115 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/cloud/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"integration_type": "system",
"iot_class": "cloud_push",
"loggers": ["hass_nabucasa"],
"requirements": ["hass-nabucasa==0.85.0"],
"requirements": ["hass-nabucasa==0.86.0"],
"single_config_entry": true
}
11 changes: 3 additions & 8 deletions homeassistant/components/deako/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

import logging

from pydeako.deako import Deako, DeviceListTimeout, FindDevicesTimeout
from pydeako.discover import DeakoDiscoverer
from pydeako import Deako, DeakoDiscoverer, FindDevicesError

from homeassistant.components import zeroconf
from homeassistant.config_entries import ConfigEntry
Expand All @@ -30,12 +29,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: DeakoConfigEntry) -> boo
await connection.connect()
try:
await connection.find_devices()
except DeviceListTimeout as exc: # device list never received
_LOGGER.warning("Device not responding to device list")
await connection.disconnect()
raise ConfigEntryNotReady(exc) from exc
except FindDevicesTimeout as exc: # total devices expected not received
_LOGGER.warning("Device not responding to device requests")
except FindDevicesError as exc:
_LOGGER.warning("Error finding devices: %s", exc)
await connection.disconnect()
raise ConfigEntryNotReady(exc) from exc

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/deako/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Config flow for deako."""

from pydeako.discover import DeakoDiscoverer, DevicesNotFoundException
from pydeako import DeakoDiscoverer, DevicesNotFoundException

from homeassistant.components import zeroconf
from homeassistant.core import HomeAssistant
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/deako/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Any

from pydeako.deako import Deako
from pydeako import Deako

from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
from homeassistant.core import HomeAssistant
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/deako/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"documentation": "https://www.home-assistant.io/integrations/deako",
"iot_class": "local_polling",
"loggers": ["pydeako"],
"requirements": ["pydeako==0.5.4"],
"requirements": ["pydeako==0.6.0"],
"single_config_entry": true,
"zeroconf": ["_deako._tcp.local."]
}
4 changes: 2 additions & 2 deletions homeassistant/components/ecovacs/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ async def initialize(self) -> None:
for device_config in devices.not_supported:
_LOGGER.warning(
(
'Device "%s" not supported. Please add support for it to '
"https://github.com/DeebotUniverse/client.py: %s"
'Device "%s" not supported. More information at '
"https://github.com/DeebotUniverse/client.py/issues/612: %s"
),
device_config["deviceName"],
device_config,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ecovacs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/ecovacs",
"iot_class": "cloud_push",
"loggers": ["sleekxmppfs", "sucks", "deebot_client"],
"requirements": ["py-sucks==0.9.10", "deebot-client==9.1.0"]
"requirements": ["py-sucks==0.9.10", "deebot-client==9.2.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/elmax/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def check_local_version_supported(api_version: str | None) -> bool:
class DirectPanel(PanelEntry):
"""Helper class for wrapping a directly accessed Elmax Panel."""

def __init__(self, panel_uri):
def __init__(self, panel_uri) -> None:
"""Construct the object."""
super().__init__(panel_uri, True, {})

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/elmax/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ async def _test_direct_and_create_entry(self):

async def async_step_direct(self, user_input: dict[str, Any]) -> ConfigFlowResult:
"""Handle the direct setup step."""
self._selected_mode = CONF_ELMAX_MODE_CLOUD
self._selected_mode = CONF_ELMAX_MODE_DIRECT
if user_input is None:
return self.async_show_form(
step_id=CONF_ELMAX_MODE_DIRECT,
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/elmax/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ async def async_stop_cover(self, **kwargs: Any) -> None:
else:
_LOGGER.debug("Ignoring stop request as the cover is IDLE")

async def async_open_cover(self, **kwargs):
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
await self.coordinator.http_client.execute_command(
endpoint_id=self._device.endpoint_id, command=CoverCommand.UP
)

async def async_close_cover(self, **kwargs):
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the cover."""
await self.coordinator.http_client.execute_command(
endpoint_id=self._device.endpoint_id, command=CoverCommand.DOWN
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/elmax/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/elmax",
"iot_class": "cloud_polling",
"loggers": ["elmax_api"],
"requirements": ["elmax-api==0.0.6.1"],
"requirements": ["elmax-api==0.0.6.3"],
"zeroconf": [
{
"type": "_elmax-ssl._tcp.local."
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/esphome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"loggers": ["aioesphomeapi", "noiseprotocol", "bleak_esphome"],
"mqtt": ["esphome/discover/#"],
"requirements": [
"aioesphomeapi==27.0.3",
"aioesphomeapi==28.0.0",
"esphome-dashboard-api==1.2.3",
"bleak-esphome==1.1.0"
],
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20241127.4"]
"requirements": ["home-assistant-frontend==20241127.6"]
}
10 changes: 7 additions & 3 deletions homeassistant/components/google_tasks/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from datetime import date, datetime, timedelta
from datetime import UTC, date, datetime, timedelta
from typing import Any, cast

from homeassistant.components.todo import (
Expand Down Expand Up @@ -39,8 +39,10 @@ def _convert_todo_item(item: TodoItem) -> dict[str, str | None]:
else:
result["status"] = TodoItemStatus.NEEDS_ACTION
if (due := item.due) is not None:
# due API field is a timestamp string, but with only date resolution
result["due"] = dt_util.start_of_local_day(due).isoformat()
# due API field is a timestamp string, but with only date resolution.
# The time portion of the date is always discarded by the API, so we
# always set to UTC.
result["due"] = dt_util.start_of_local_day(due).replace(tzinfo=UTC).isoformat()
else:
result["due"] = None
result["notes"] = item.description
Expand All @@ -51,6 +53,8 @@ def _convert_api_item(item: dict[str, str]) -> TodoItem:
"""Convert tasks API items into a TodoItem."""
due: date | None = None
if (due_str := item.get("due")) is not None:
# Due dates are returned always in UTC so we only need to
# parse the date portion which will be interpreted as a a local date.
due = datetime.fromisoformat(due_str).date()
return TodoItem(
summary=item["title"],
Expand Down
14 changes: 11 additions & 3 deletions homeassistant/components/http/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from collections.abc import Mapping
from pathlib import Path
import sys
from typing import Final

from aiohttp.hdrs import CACHE_CONTROL, CONTENT_TYPE
Expand All @@ -17,6 +18,15 @@
CACHE_HEADERS: Mapping[str, str] = {CACHE_CONTROL: CACHE_HEADER}
RESPONSE_CACHE: LRU[tuple[str, Path], tuple[Path, str]] = LRU(512)

if sys.version_info >= (3, 13):
# guess_type is soft-deprecated in 3.13
# for paths and should only be used for
# URLs. guess_file_type should be used
# for paths instead.
_GUESSER = CONTENT_TYPES.guess_file_type
else:
_GUESSER = CONTENT_TYPES.guess_type


class CachingStaticResource(StaticResource):
"""Static Resource handler that will add cache headers."""
Expand All @@ -37,9 +47,7 @@ async def _handle(self, request: Request) -> StreamResponse:
# Must be directory index; ignore caching
return response
file_path = response._path # noqa: SLF001
response.content_type = (
CONTENT_TYPES.guess_type(file_path)[0] or FALLBACK_CONTENT_TYPE
)
response.content_type = _GUESSER(file_path)[0] or FALLBACK_CONTENT_TYPE
# Cache actual header after setter construction.
content_type = response.headers[CONTENT_TYPE]
RESPONSE_CACHE[key] = (file_path, content_type)
Expand Down
23 changes: 18 additions & 5 deletions homeassistant/components/nordpool/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
PARALLEL_UPDATES = 0


def get_prices(data: DeliveryPeriodData) -> dict[str, tuple[float, float, float]]:
def get_prices(
data: DeliveryPeriodData,
) -> dict[str, tuple[float | None, float, float | None]]:
"""Return previous, current and next prices.
Output: {"SE3": (10.0, 10.5, 12.1)}
Expand All @@ -39,17 +41,28 @@ def get_prices(data: DeliveryPeriodData) -> dict[str, tuple[float, float, float]
previous_time = current_time - timedelta(hours=1)
next_time = current_time + timedelta(hours=1)
price_data = data.entries
LOGGER.debug("Price data: %s", price_data)
for entry in price_data:
if entry.start <= current_time <= entry.end:
current_price_entries = entry.entry
if entry.start <= previous_time <= entry.end:
last_price_entries = entry.entry
if entry.start <= next_time <= entry.end:
next_price_entries = entry.entry
LOGGER.debug(
"Last price %s, current price %s, next price %s",
last_price_entries,
current_price_entries,
next_price_entries,
)

result = {}
for area, price in current_price_entries.items():
result[area] = (last_price_entries[area], price, next_price_entries[area])
result[area] = (
last_price_entries.get(area),
price,
next_price_entries.get(area),
)
LOGGER.debug("Prices: %s", result)
return result

Expand Down Expand Up @@ -90,7 +103,7 @@ class NordpoolDefaultSensorEntityDescription(SensorEntityDescription):
class NordpoolPricesSensorEntityDescription(SensorEntityDescription):
"""Describes Nord Pool prices sensor entity."""

value_fn: Callable[[tuple[float, float, float]], float | None]
value_fn: Callable[[tuple[float | None, float, float | None]], float | None]


@dataclass(frozen=True, kw_only=True)
Expand Down Expand Up @@ -136,13 +149,13 @@ class NordpoolBlockPricesSensorEntityDescription(SensorEntityDescription):
NordpoolPricesSensorEntityDescription(
key="last_price",
translation_key="last_price",
value_fn=lambda data: data[0] / 1000,
value_fn=lambda data: data[0] / 1000 if data[0] else None,
suggested_display_precision=2,
),
NordpoolPricesSensorEntityDescription(
key="next_price",
translation_key="next_price",
value_fn=lambda data: data[2] / 1000,
value_fn=lambda data: data[2] / 1000 if data[2] else None,
suggested_display_precision=2,
),
)
Expand Down
8 changes: 7 additions & 1 deletion homeassistant/components/number/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,13 @@ class NumberDeviceClass(StrEnum):
NumberDeviceClass.PM10: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
NumberDeviceClass.PM25: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
NumberDeviceClass.POWER_FACTOR: {PERCENTAGE, None},
NumberDeviceClass.POWER: {UnitOfPower.WATT, UnitOfPower.KILO_WATT},
NumberDeviceClass.POWER: {
UnitOfPower.WATT,
UnitOfPower.KILO_WATT,
UnitOfPower.MEGA_WATT,
UnitOfPower.GIGA_WATT,
UnitOfPower.TERA_WATT,
},
NumberDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth),
NumberDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux),
NumberDeviceClass.PRESSURE: set(UnitOfPressure),
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/samsungtv/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"requirements": [
"getmac==0.9.4",
"samsungctl[websocket]==0.7.1",
"samsungtvws[async,encrypted]==2.7.1",
"samsungtvws[async,encrypted]==2.7.2",
"wakeonlan==2.1.0",
"async-upnp-client==0.41.0"
],
Expand Down
8 changes: 7 additions & 1 deletion homeassistant/components/sensor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,13 @@ class SensorStateClass(StrEnum):
SensorDeviceClass.PM10: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
SensorDeviceClass.PM25: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
SensorDeviceClass.POWER_FACTOR: {PERCENTAGE, None},
SensorDeviceClass.POWER: {UnitOfPower.WATT, UnitOfPower.KILO_WATT},
SensorDeviceClass.POWER: {
UnitOfPower.WATT,
UnitOfPower.KILO_WATT,
UnitOfPower.MEGA_WATT,
UnitOfPower.GIGA_WATT,
UnitOfPower.TERA_WATT,
},
SensorDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth),
SensorDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux),
SensorDeviceClass.PRESSURE: set(UnitOfPressure),
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tesla_fleet/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
Scope.OPENID,
Scope.OFFLINE_ACCESS,
Scope.VEHICLE_DEVICE_DATA,
Scope.VEHICLE_LOCATION,
Scope.VEHICLE_CMDS,
Scope.VEHICLE_CHARGING_CMDS,
Scope.ENERGY_DEVICE_DATA,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/tesla_fleet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/tesla_fleet",
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"requirements": ["tesla-fleet-api==0.8.4"]
"requirements": ["tesla-fleet-api==0.8.5"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/teslemetry/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/teslemetry",
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"requirements": ["tesla-fleet-api==0.8.4", "teslemetry-stream==0.4.2"]
"requirements": ["tesla-fleet-api==0.8.5", "teslemetry-stream==0.4.2"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/tessie/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/tessie",
"iot_class": "cloud_polling",
"loggers": ["tessie", "tesla-fleet-api"],
"requirements": ["tessie-api==0.1.1", "tesla-fleet-api==0.8.4"]
"requirements": ["tessie-api==0.1.1", "tesla-fleet-api==0.8.5"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/tplink/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,5 +300,5 @@
"documentation": "https://www.home-assistant.io/integrations/tplink",
"iot_class": "local_polling",
"loggers": ["kasa"],
"requirements": ["python-kasa[speedups]==0.8.0"]
"requirements": ["python-kasa[speedups]==0.8.1"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/upb/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/upb",
"iot_class": "local_push",
"loggers": ["upb_lib"],
"requirements": ["upb-lib==0.5.8"]
"requirements": ["upb-lib==0.5.9"]
}
13 changes: 8 additions & 5 deletions homeassistant/components/utility_meter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Support for tracking consumption over given periods of time."""

from datetime import timedelta
from datetime import datetime, timedelta
import logging

from croniter import croniter
from cronsim import CronSim, CronSimError
import voluptuous as vol

from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
Expand Down Expand Up @@ -47,9 +47,12 @@

def validate_cron_pattern(pattern):
"""Check that the pattern is well-formed."""
if croniter.is_valid(pattern):
return pattern
raise vol.Invalid("Invalid pattern")
try:
CronSim(pattern, datetime(2020, 1, 1)) # any date will do
except CronSimError as err:
_LOGGER.error("Invalid cron pattern %s: %s", pattern, err)
raise vol.Invalid("Invalid pattern") from err
return pattern


def period_or_cron(config):
Expand Down
1 change: 0 additions & 1 deletion homeassistant/components/utility_meter/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"documentation": "https://www.home-assistant.io/integrations/utility_meter",
"integration_type": "helper",
"iot_class": "local_push",
"loggers": ["croniter"],
"quality_scale": "internal",
"requirements": ["cronsim==2.6"]
}
2 changes: 1 addition & 1 deletion homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
APPLICATION_NAME: Final = "HomeAssistant"
MAJOR_VERSION: Final = 2024
MINOR_VERSION: Final = 12
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, 12, 0)
Expand Down
Loading

0 comments on commit cf53a97

Please sign in to comment.