Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ jobs:
persist-credentials: false

- name: Initialize CodeQL
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
uses: github/codeql-action/init@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
languages: python

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
uses: github/codeql-action/analyze@d1ba80a13dd99fba24a470575428917156a28b43 # v4.37.5
with:
category: "/language:python"
8 changes: 7 additions & 1 deletion homeassistant/components/gatus/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import UnitOfTime
from homeassistant.const import EntityCategory, UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

Expand Down Expand Up @@ -42,6 +42,12 @@ class GatusSensorEntityDescription(SensorEntityDescription):
else None
),
),
GatusSensorEntityDescription(
key="status_code",
translation_key="status_code",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda result: result.status,
),
)


Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/gatus/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
"sensor": {
"response_time": {
"name": "Response time"
},
"status_code": {
"name": "Status code"
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/google/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["googleapiclient"],
"requirements": ["gcal-sync==9.1.0", "oauth2client==4.1.3", "ical==14.0.1"]
"requirements": ["gcal-sync==9.1.0", "oauth2client==4.1.3", "ical==14.1.0"]
}
55 changes: 36 additions & 19 deletions homeassistant/components/immich/media_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,33 +140,33 @@ async def async_browse_media(
if item.identifier:
can_search = bool(ImmichMediaSourceIdentifier(item.identifier).unique_id)

title, children = await self._async_build_immich(item, entries)

return BrowseMediaSource(
domain=DOMAIN,
identifier=item.identifier,
media_class=MediaClass.DIRECTORY,
media_content_type=MediaClass.IMAGE,
title="Immich",
title=title,
can_play=False,
can_expand=True,
can_search=can_search,
search_media_classes=[MediaClass.IMAGE, MediaClass.VIDEO],
children_media_class=MediaClass.DIRECTORY,
children=[
*await self._async_build_immich(item, entries),
],
children=children,
)

async def _async_build_immich(
self, item: MediaSourceItem, entries: list[ConfigEntry]
) -> list[BrowseMediaSource]:
"""Handle browsing different immich instances."""
) -> tuple[str, list[BrowseMediaSource]]:
"""Return the title and the children of the browsed item."""

# --------------------------------------------------------
# root level, render immich instances
# --------------------------------------------------------
if not item.identifier:
LOGGER.debug("Render all Immich instances")
return [
return "Immich", [
BrowseMediaSource(
domain=DOMAIN,
identifier=entry.unique_id,
Expand All @@ -193,7 +193,7 @@ async def _async_build_immich(

if identifier.collection is None:
LOGGER.debug("Render all collections for %s", entry.title)
return [
return entry.title, [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{identifier.unique_id}|{collection}",
Expand Down Expand Up @@ -221,9 +221,9 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return identifier.collection, []

return [
return identifier.collection, [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{identifier.unique_id}|albums|{album.album_id}",
Expand All @@ -248,9 +248,9 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return identifier.collection, []

return [
return identifier.collection, [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{identifier.unique_id}|tags|{tag.tag_id}",
Expand All @@ -274,9 +274,9 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return identifier.collection, []

return [
return identifier.collection, [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{identifier.unique_id}|people|{person.person_id}",
Expand All @@ -295,13 +295,17 @@ async def _async_build_immich(
# --------------------------------------------------------
assert identifier.collection_id is not None
assets: list[ImmichAsset] = []
title = identifier.collection
if identifier.collection == "albums":
LOGGER.debug(
"Render all assets of album %s for %s",
identifier.collection_id,
entry.title,
)
try:
album = await immich_api.albums.async_get_album_info(
identifier.collection_id
)
assets = await immich_api.search.async_get_all_by_album_ids(
[identifier.collection_id]
)
Expand All @@ -312,14 +316,19 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return title, []

title = album.album_name

elif identifier.collection == "tags":
LOGGER.debug(
"Render all assets with tag %s",
identifier.collection_id,
)
try:
tag = await immich_api.tags.async_get_tag_by_id(
identifier.collection_id
)
assets = await immich_api.search.async_get_all_by_tag_ids(
[identifier.collection_id]
)
Expand All @@ -330,14 +339,19 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return title, []

title = tag.name

elif identifier.collection == "people":
LOGGER.debug(
"Render all assets for person %s",
identifier.collection_id,
)
try:
person = await immich_api.people.async_get_person_by_id(
identifier.collection_id
)
assets = await immich_api.search.async_get_all_by_person_ids(
[identifier.collection_id]
)
Expand All @@ -348,7 +362,10 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return title, []

title = person.name

elif identifier.collection == "favorites":
LOGGER.debug("Render all assets for favorites collection")
try:
Expand All @@ -360,9 +377,9 @@ async def _async_build_immich(
translation_placeholders={"msg": str(err)},
) from err
except ImmichError:
return []
return title, []

return _parse_assets(assets, identifier)
return title, _parse_assets(assets, identifier)

@override
async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
Expand Down
24 changes: 14 additions & 10 deletions homeassistant/components/knx/telegrams.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@
EVICT_EXPIRED_HOUR = 3

# Interval at which buffered telegram writes are flushed to the database.
# Websocket queries flush on demand (``flush_first=True``), so the only telegrams
# at risk from a longer interval are those buffered during an ungraceful shutdown.
FLUSH_INTERVAL_SECONDS = 600
# Postgres flushes far more often than sqlite: push-based consumers, unlike
# on-demand-flushed (``flush_first=True``) queries, only see a telegram once
# it is actually written.
FLUSH_INTERVAL_SECONDS_SQLITE = 600
FLUSH_INTERVAL_SECONDS_POSTGRES = 1

# The buffer drops the oldest telegrams when full. Size it to cover a full
# flush interval at ~50 telegrams/s, the maximum rate of a KNX TP line, so
# nothing is dropped while the database is healthy.
MAX_BUFFER_TELEGRAMS = FLUSH_INTERVAL_SECONDS * 50
# flush interval at ~50 telegrams/s, the maximum rate of a single KNX TP line,
# times 4 for headroom - routing can record multiple TP lines concurrently -
# so nothing is dropped while the database is healthy.
MAX_BUFFER_TELEGRAMS_SQLITE = FLUSH_INTERVAL_SECONDS_SQLITE * 50 * 4
MAX_BUFFER_TELEGRAMS_POSTGRES = FLUSH_INTERVAL_SECONDS_POSTGRES * 50 * 4

# Timeout for the migration probe and store initialization, so an unreachable
# database cannot block KNX setup until the driver/OS connection timeout expires.
Expand Down Expand Up @@ -127,17 +131,17 @@ def __init__(
self._uninitialized_store = BufferedPostgresStore(
self.dsn,
retention_days=self.retention_days,
flush_interval=FLUSH_INTERVAL_SECONDS,
max_buffer_size=MAX_BUFFER_TELEGRAMS,
flush_interval=FLUSH_INTERVAL_SECONDS_POSTGRES,
max_buffer_size=MAX_BUFFER_TELEGRAMS_POSTGRES,
)
else:
full_path = hass.config.path(STORAGE_DIR, KNX_TELEGRAM_DB_PATH_SQLITE)
os.makedirs(os.path.dirname(full_path), exist_ok=True)
self._uninitialized_store = BufferedSqliteStore(
full_path,
retention_days=self.retention_days,
flush_interval=FLUSH_INTERVAL_SECONDS,
max_buffer_size=MAX_BUFFER_TELEGRAMS,
flush_interval=FLUSH_INTERVAL_SECONDS_SQLITE,
max_buffer_size=MAX_BUFFER_TELEGRAMS_SQLITE,
)

self._xknx_telegram_cb_handle = (
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/knx/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ async def register_panel(hass: HomeAssistant) -> None:
module_url=f"{URL_BASE}/{knx_panel.entrypoint_js}",
embed_iframe=True,
require_admin=True,
handle_safe_area=True,
)


Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/local_calendar/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/local_calendar",
"iot_class": "local_polling",
"loggers": ["ical"],
"requirements": ["ical==14.0.1"]
"requirements": ["ical==14.1.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/local_todo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/local_todo",
"iot_class": "local_polling",
"requirements": ["ical==14.0.1"]
"requirements": ["ical==14.1.0"]
}
10 changes: 10 additions & 0 deletions homeassistant/components/panel_custom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
CONF_TRUST_EXTERNAL_SCRIPT = "trust_external_script"
CONF_URL_EXCLUSIVE_GROUP = "url_exclusive_group"
CONF_REQUIRE_ADMIN = "require_admin"
CONF_HANDLE_SAFE_AREA = "handle_safe_area"

DEFAULT_EMBED_IFRAME = False
DEFAULT_TRUST_EXTERNAL = False
DEFAULT_HANDLE_SAFE_AREA = False

DEFAULT_ICON = "mdi:bookmark"
LEGACY_URL = "/api/panel_custom/{}"
Expand Down Expand Up @@ -59,6 +61,9 @@
default=DEFAULT_TRUST_EXTERNAL,
): cv.boolean,
vol.Optional(CONF_REQUIRE_ADMIN, default=False): cv.boolean,
vol.Optional(
CONF_HANDLE_SAFE_AREA, default=DEFAULT_HANDLE_SAFE_AREA
): cv.boolean,
}
),
],
Expand Down Expand Up @@ -92,6 +97,9 @@ async def async_register_panel(
# If your panel is used to configure an integration,
# needs the domain of the integration
config_panel_domain: str | None = None,
# If your panel handles the safe area insets itself, opting out of the
# padding Home Assistant would otherwise add around it
handle_safe_area: bool = DEFAULT_HANDLE_SAFE_AREA,
) -> None:
"""Register a new custom panel."""
if js_url is None and module_url is None:
Expand All @@ -103,6 +111,7 @@ async def async_register_panel(
"name": webcomponent_name,
"embed_iframe": embed_iframe,
"trust_external": trust_external,
"handle_safe_area": handle_safe_area,
}

if js_url is not None:
Expand Down Expand Up @@ -148,6 +157,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"trust_external": panel[CONF_TRUST_EXTERNAL_SCRIPT],
"embed_iframe": panel[CONF_EMBED_IFRAME],
"require_admin": panel[CONF_REQUIRE_ADMIN],
"handle_safe_area": panel[CONF_HANDLE_SAFE_AREA],
}

if CONF_JS_URL in panel:
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/remote_calendar/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["ical"],
"quality_scale": "silver",
"requirements": ["ical==14.0.1"]
"requirements": ["ical==14.1.0"]
}
Loading
Loading